diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 354d3242a9..513f955e9e 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -46,6 +46,8 @@ const char* SRGB_TO_LINEAR_FRAG = R"SCRIBE( +// OpenGLDisplayPlugin_present.frag + uniform sampler2D colorMap; in vec2 varTexCoord0; diff --git a/libraries/gl/src/gl/GLShaders.cpp b/libraries/gl/src/gl/GLShaders.cpp index bddd657b69..9bfe214fcf 100644 --- a/libraries/gl/src/gl/GLShaders.cpp +++ b/libraries/gl/src/gl/GLShaders.cpp @@ -275,7 +275,7 @@ GLuint gl::compileProgram(const std::vector& glshaders, std::string& mes return glprogram; } -static const QString& getShaderCacheFile() { +const QString& getShaderCacheFile() { static const QString SHADER_CACHE_FOLDER{ "shaders" }; static const QString SHADER_CACHE_FILE_NAME{ "cache.json" }; static const QString SHADER_CACHE_FILE = FileUtils::standardPath(SHADER_CACHE_FOLDER) + SHADER_CACHE_FILE_NAME; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp index a225eeeec2..af6a0df297 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp @@ -154,6 +154,8 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::Co return object; } +std::atomic gpuBinaryShadersLoaded; + GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler) { if (!program.isProgram()) { return nullptr; @@ -182,6 +184,9 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader:: // If we have a cached binary program, try to load it instead of compiling the individual shaders if (cachedBinary) { glprogram = ::gl::compileProgram({}, compilationLogs[version].message, cachedBinary); + if (0 != glprogram) { + ++gpuBinaryShadersLoaded; + } } // If we have no program, then either no cached binary, or the binary failed to load (perhaps a GPU driver update invalidated the cache) diff --git a/tests/gpu/src/ShaderLoadTest.cpp b/tests/gpu/src/ShaderLoadTest.cpp index 800bd9092a..09752dc385 100644 --- a/tests/gpu/src/ShaderLoadTest.cpp +++ b/tests/gpu/src/ShaderLoadTest.cpp @@ -16,18 +16,19 @@ #include #include #include - +#include #include #include #include #include -//#pragma optimize("", off) - QTEST_MAIN(ShaderLoadTest) -#define FAIL_AFTER_SECONDS 30 +extern std::atomic gpuBinaryShadersLoaded; + +extern const QString& getShaderCacheFile(); + QtMessageHandler originalHandler; @@ -39,24 +40,188 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt originalHandler(type, context, message); } -void ShaderLoadTest::loadProgramSources() { - _programSources.clear(); - QString json = FileUtils::readFile(":cache.json"); +std::pair>> parseCachedShaderString(const QString& cachedShaderString) { + + std::pair>> result; + { + static const QRegularExpression versionRegex("^// VERSION (\\d+)"); + auto match = versionRegex.match(cachedShaderString); + result.first = match.captured(1).toInt(); + } + + + int rangeStart = 0; + QString type; + static const QRegularExpression regex("//-------- (\\w+)"); + auto match = regex.match(cachedShaderString, rangeStart); + while (match.hasMatch()) { + auto newType = match.captured(1); + auto start = match.capturedStart(0); + auto end = match.capturedEnd(0); + if (rangeStart != 0) { + QString subString = cachedShaderString.mid(rangeStart, start - rangeStart); + result.second.emplace_back(type, subString); + } + rangeStart = end; + type = newType; + match = regex.match(cachedShaderString, rangeStart); + } + + if (rangeStart != 0) { + QString subString = cachedShaderString.mid(rangeStart); + result.second.emplace_back(type, subString); + } + return result; +} + +std::string getShaderName(const QString& shader) { + static const QRegularExpression nameExp("//\\s+(\\w+\\.(?:vert|frag))"); + auto match = nameExp.match(shader); + if (!match.hasMatch()) { + return (QCryptographicHash::hash(shader.toUtf8(), QCryptographicHash::Md5).toHex() + ".shader").toStdString(); + } + return match.captured(1).trimmed().toStdString(); +} + +void ShaderLoadTest::randomizeShaderSources() { + for (auto& entry : _shaderSources) { + entry.second += ("\n//" + QUuid::createUuid().toString()).toStdString(); + } +} + +#if USE_LOCAL_SHADERS +const QString SHADER_CACHE_FILENAME = "c:/Users/bdavi/AppData/Local/High Fidelity - dev/Interface/shaders/cache.json"; +static const QString SHADER_FOLDER = "D:/shaders/"; +void ShaderLoadTest::parseCacheDirectory() { + for (const auto& shaderFile : QDir(SHADER_FOLDER).entryList(QDir::Files)) { + QString shaderSource = FileUtils::readFile(SHADER_FOLDER + "/" + shaderFile); + _shaderSources[shaderFile.trimmed().toStdString()] = shaderSource.toStdString(); + } + + auto programsDoc = QJsonDocument::fromJson(FileUtils::readFile(SHADER_FOLDER + "programs.json").toUtf8()); + for (const auto& programElement : programsDoc.array()) { + auto programObj = programElement.toObject(); + QString vertexSource = programObj["vertex"].toString(); + QString pixelSource = programObj["pixel"].toString(); + _programs.insert({ vertexSource.toStdString(), pixelSource.toStdString() }); + } +} + +void ShaderLoadTest::persistCacheDirectory() { + for (const auto& shaderFile : QDir(SHADER_FOLDER).entryList(QDir::Files)) { + QFile(SHADER_FOLDER + "/" + shaderFile).remove(); + } + + // Write the shader source files + for (const auto& entry : _shaderSources) { + const QString name = entry.first.c_str(); + const QString shader = entry.second.c_str(); + QString fullFile = SHADER_FOLDER + name; + QVERIFY(!QFileInfo(fullFile).exists()); + QFile shaderFile(fullFile); + shaderFile.open(QIODevice::WriteOnly); + shaderFile.write(shader.toUtf8()); + shaderFile.close(); + } + + // Write the list of programs + { + QVariantList programsList; + for (const auto& program : _programs) { + QVariantMap programMap; + programMap["vertex"] = program.first.c_str(); + programMap["pixel"] = program.second.c_str(); + programsList.push_back(programMap); + } + + QFile saveFile(SHADER_FOLDER + "programs.json"); + saveFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + saveFile.write(QJsonDocument::fromVariant(programsList).toJson(QJsonDocument::Indented)); + saveFile.close(); + } +} +#else +const QString SHADER_CACHE_FILENAME = ":cache.json"; +#endif + +void ShaderLoadTest::parseCacheFile() { + QString json = FileUtils::readFile(SHADER_CACHE_FILENAME); auto root = QJsonDocument::fromJson(json.toUtf8()).object(); - _programSources.reserve(root.size()); - QRegularExpression regex("//-------- \\d"); - for (auto shaderKey : root.keys()) { + _programs.clear(); + _programs.reserve(root.size()); + + const auto keys = root.keys(); + Program program; + for (auto shaderKey : keys) { auto cacheEntry = root[shaderKey].toObject(); auto source = cacheEntry["source"].toString(); - auto split = source.split(regex, QString::SplitBehavior::SkipEmptyParts); - _programSources.emplace_back(split.at(0).trimmed().toStdString(), split.at(1).trimmed().toStdString()); + auto shaders = parseCachedShaderString(source); + for (const auto& entry : shaders.second) { + const auto& type = entry.first; + const auto& source = entry.second; + const auto name = getShaderName(source); + if (name.empty()) { + continue; + } + if (0 == _shaderSources.count(name)) { + _shaderSources[name] = source.toStdString(); + } + if (type == "vertex") { + program.first = name; + } else if (type == "pixel") { + program.second = name; + } + } + // FIXME support geometry / tesselation shaders eventually + if (program.first.empty() || program.second.empty()) { + qFatal("Bad Shader Setup"); + } + _programs.insert(program); } } +bool ShaderLoadTest::buildProgram(const Program& programFiles) { + const auto& vertexName = programFiles.first; + const auto& vertexSource = _shaderSources[vertexName]; + auto vertexShader = gpu::Shader::createVertex({ vertexSource }); + + const auto& pixelName = programFiles.second; + const auto& pixelSource = _shaderSources[pixelName]; + auto pixelShader = gpu::Shader::createPixel({ pixelSource }); + + auto program = gpu::Shader::createProgram(vertexShader, pixelShader); + return gpu::gl::GLBackend::makeProgram(*program, {}, {}); +} void ShaderLoadTest::initTestCase() { originalHandler = qInstallMessageHandler(messageHandler); - loadProgramSources(); + DependencyManager::set(); + { + const auto& shaderCacheFile = getShaderCacheFile(); + if (QFileInfo(shaderCacheFile).exists()) { + QFile(shaderCacheFile).remove(); + } + } + + // For local debugging +#if USE_LOCAL_SHADERS + parseCacheFile(); + persistCacheDirectory(); + parseCacheDirectory(); +#else + parseCacheFile(); +#endif + + // We use this to defeat shader caching both by the GPU backend + // and the OpenGL driver + randomizeShaderSources(); + + QVERIFY(!_programs.empty()); + for (const auto& program : _programs) { + QVERIFY(_shaderSources.count(program.first) == 1); + QVERIFY(_shaderSources.count(program.second) == 1); + } + getDefaultOpenGLSurfaceFormat(); _canvas.create(); if (!_canvas.makeCurrent()) { @@ -64,40 +229,59 @@ void ShaderLoadTest::initTestCase() { } gl::initModuleGl(); gpu::Context::init(); - _gpuContext = std::make_shared(); _canvas.makeCurrent(); - DependencyManager::set(); } void ShaderLoadTest::cleanupTestCase() { - _gpuContext->recycle(); - _gpuContext->shutdown(); - _gpuContext.reset(); DependencyManager::destroy(); } -std::string randomString() { - return "\n//" + QUuid::createUuid().toString().toStdString(); -} - -std::unordered_map cachedShaders; - -gpu::ShaderPointer getShader(const std::string& shaderSource, bool pixel) { - if (0 != cachedShaders.count(shaderSource)) { - return cachedShaders[shaderSource]; - } - auto shader = pixel ? gpu::Shader::createPixel({ shaderSource + randomString() }) : gpu::Shader::createVertex({ shaderSource + randomString() }); - cachedShaders.insert({shaderSource, shader}); - return shader; -} - void ShaderLoadTest::testShaderLoad() { - QBENCHMARK { - for (const auto& programSource : _programSources) { - auto vertexShader = getShader(programSource.first, false); - auto pixelShader = getShader(programSource.second, true); - auto program = gpu::Shader::createProgram(vertexShader, pixelShader); - QVERIFY(gpu::gl::GLBackend::makeProgram(*program, {}, {})); + auto gpuContext = std::make_shared(); + QVERIFY(gpuBinaryShadersLoaded == 0); + + QElapsedTimer timer; + + // Initial load of all the shaders + // No caching + { + timer.start(); + for (const auto& program : _programs) { + QVERIFY(buildProgram(program)); } + qDebug() << "Uncached shader load took" << timer.elapsed() << "ms"; + QVERIFY(gpuBinaryShadersLoaded == 0); } + gpuContext->recycle(); + glFinish(); + + // Reload the shaders within the same GPU context lifetime. + // Shaders will use the cached binaries in memory + { + timer.start(); + for (const auto& program : _programs) { + QVERIFY(buildProgram(program)); + } + qDebug() << "Cached shader load took" << timer.elapsed() << "ms"; + QVERIFY(gpuBinaryShadersLoaded == _programs.size() * gpu::gl::GLShader::NumVersions); + } + + // Simulate reloading the shader cache from disk by destroying and recreating the gpu context + // Shaders will use the cached binaries from disk + { + gpuBinaryShadersLoaded = 0; + gpuContext->recycle(); + gpuContext->shutdown(); + gpuContext.reset(); + gpuContext = std::make_shared(); + _canvas.makeCurrent(); + timer.start(); + for (const auto& program : _programs) { + QVERIFY(buildProgram(program)); + } + qDebug() << "Cached shader load took" << timer.elapsed() << "ms"; + QVERIFY(gpuBinaryShadersLoaded == _programs.size() * gpu::gl::GLShader::NumVersions); + } + } + diff --git a/tests/gpu/src/ShaderLoadTest.h b/tests/gpu/src/ShaderLoadTest.h index ca0f8757ca..cfb01501b2 100644 --- a/tests/gpu/src/ShaderLoadTest.h +++ b/tests/gpu/src/ShaderLoadTest.h @@ -8,17 +8,44 @@ #pragma once +#include +#include + #include #include #include #include +#define USE_LOCAL_SHADERS 0 + +namespace std { + template <> + struct hash> { + size_t operator()(const std::pair& a) const { + std::hash hasher; + return hasher(a.first) + hasher(a.second); + } + }; + +} + +using ShadersByName = std::unordered_map; +using Program = std::pair; +using Programs = std::unordered_set; + class ShaderLoadTest : public QObject { Q_OBJECT private: - void loadProgramSources(); + + void parseCacheFile(); +#if USE_LOCAL_SHADERS + void parseCacheDirectory(); + void persistCacheDirectory(); +#endif + bool buildProgram(const Program& program); + void randomizeShaderSources(); private slots: void initTestCase(); @@ -27,12 +54,10 @@ private slots: private: - using ProgramSource = std::pair; - using ProgramSources = std::vector; - ProgramSources _programSources; + ShadersByName _shaderSources; + Programs _programs; QString _resourcesPath; OffscreenGLCanvas _canvas; - gpu::ContextPointer _gpuContext; const glm::uvec2 _size{ 640, 480 }; }; diff --git a/tests/gpu/src/cache.json b/tests/gpu/src/cache.json index 516d0ffe04..ccec6a430f 100644 --- a/tests/gpu/src/cache.json +++ b/tests/gpu/src/cache.json @@ -1,358 +1,512 @@ { - "+MdOQDfssGACXpWO/WIoQA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_translucent.slv\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n\n\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "+Fz1iUM9mAnsczReJey3+g==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_unlit.frag\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a);\n}\n\n" }, - "+caDhxma8yHSLEejqkKaDA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_textured_unlit.frag\n// fragment shader\n//\n// Created by Clément Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb);\n }\n}\n\n", - "type": 36385 + "+M1tIpq5A7dS3nFg+gZJNQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_ambient_light.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 9/3/14.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n _fragColor = vec4(color, 1.0);\n\n }\n}\n\n\n" }, - "+lMn5Idc7hJckZzst98DyQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_translucent.slv\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n\n\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "+mpNVPHhcBoKZ74Tq3vNoA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n\n\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n\n\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n\n\n float opacity = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n opacity = -_color.a;\n }\n opacity *= texel.a;\n vec3 albedo = _color.rgb * texel.rgb;\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n 1.0,\n fragPosition,\n fragNormal,\n albedo,\n DEFAULT_FRESNEL,\n 0.0f,\n fadeEmissive,\n DEFAULT_ROUGHNESS,\n opacity),\n opacity);\n\n}\n\n" }, - "/zsR3v64Z21U62A+Uimiug==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n\n\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "/9KkHjVgFwvEDKxSPMy6/Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "0iMGvLIYf7QIpUV2kRLbKA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n\n\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\n\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "/QdKNQu/OZW/wZUMgFCFUw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n" }, - "2G28J9+cJskFS2LxDcxLUQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// local_lights_drawOutline.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n Light lightArray[128];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n\n\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n\n\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n // Show edges\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n \n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n\n\n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n frag.position = fragPosition;\n\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragPos = invViewMat * fragPosition;\n \n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n _fragColor = vec4(0, 0, 0, 1);\n \n int numLightTouching = 0;\n int lightClusterOffset = cluster.z;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n vec3 color = vec3(0.0);\n if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 color = vec3(0.0);\n\n if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n}\n\n\n\n", - "type": 36385 + "/ap5E6Wo+pKIeUmfBkSlXQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "2d8TR20EU2lEJAWrAC66uA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw and transform the unit quad [-1,-1 -> 1,1]\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * pos);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n", - "type": 36385 + "/nm10YJuYOiret6AZ4H4QA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "2jGenSZc627GMZVDEirH+Q==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "04pa0ArsTf+wloCY22ms2A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// skin_model_shadow_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "2jUY+Y//d3wrmTUxkD65Jw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "0F+ugd1jfwUnFqhMX+mMCQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// Haze.frag\n//\n// Created by Nissim Hadar on 9/5/2107.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n\n\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n\n\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n\n\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nuniform sampler2D colorMap;\nuniform sampler2D linearDepthMap;\n\nvec4 unpackPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearDepthMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n if ((isHazeEnabled() == 0.0) || (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) {\n discard;\n }\n\n vec4 fragColor = texture(colorMap, varTexCoord0);\n vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);\n\n mat4 viewInverse = getViewInverse();\n vec4 fragPositionWS = viewInverse * fragPositionES;\n vec4 eyePositionWS = viewInverse[3];\n\n Light light = getKeyLight();\n vec3 lightDirectionWS = getLightDirection(light);\n\n outFragColor = computeHazeColor(fragColor, fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);\n}\n\n\n" }, - "561UcZUk4hstbpE6HjA1IA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_lightmap_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_lightmap_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n\n\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n", - "type": 36385 + "0RqDfeTpMx45eqgktNgpbw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D_model.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n\n vec3 fragPosition = _positionES.xyz;\n\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalSkyboxGlobalColor(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n roughness),\n opacity);\n\n // And emissive\n color.rgb += emissive * isEmissiveEnabled();\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n" }, - "5KfqCxkqWA7/H9c8vYDw5A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// directional_ambient_light.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 9/3/14.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n _fragColor = vec4(color, 1.0);\n\n }\n}\n\n\n", - "type": 36385 + "0hQ0Rb3K0WDqHW53Tf8Kuw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\nlayout(location = 6) in float _alpha;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n" }, - "5rUxHX11/JObhuCabNQK1w==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n", - "type": 36385 + "0n2jal6anoYiLyvuCgYbqg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "6xjp4I1z6+q5Ip5fV55BFQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nuniform sampler2D linearDepthMap;\nuniform sampler2D normalMap;\n\nin vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outLinearDepth;\nlayout(location = 1) out vec4 outNormal;\n\nvoid main(void) {\n // Gather 2 by 2 quads from texture and downsample\n\n // Try different filters for Z\n vec4 Zeyes = textureGather(linearDepthMap, varTexCoord0, 0);\n // float Zeye = texture(linearDepthMap, varTexCoord0).x;\n\n vec4 rawNormalsX = textureGather(normalMap, varTexCoord0, 0);\n vec4 rawNormalsY = textureGather(normalMap, varTexCoord0, 1);\n vec4 rawNormalsZ = textureGather(normalMap, varTexCoord0, 2);\n\n float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));\n\n vec3 normal = vec3(0.0);\n normal += unpackNormal(vec3(rawNormalsX[0], rawNormalsY[0], rawNormalsZ[0]));\n normal += unpackNormal(vec3(rawNormalsX[1], rawNormalsY[1], rawNormalsZ[1]));\n normal += unpackNormal(vec3(rawNormalsX[2], rawNormalsY[2], rawNormalsZ[2]));\n normal += unpackNormal(vec3(rawNormalsX[3], rawNormalsY[3], rawNormalsZ[3]));\n\n normal = normalize(normal);\n\n outLinearDepth = vec4(Zeye, 0.0, 0.0, 0.0);\n outNormal = vec4((normal + vec3(1.0)) * 0.5, 0.0);\n}\n\n\n\n", - "type": 36385 + "15zRKjBz9e2kFmwfqMmhNw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// material_opaque_unlit.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\nlayout(location = 5) in float _alpha;\n\nvoid main(void) {\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n" }, - "A1kbySgm64qUuUTTxQuo4w==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// standardTransformPNTC.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw texture 0 fetched at texcoord.xy\n// Alpha is 1\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(texture(colorMap, varTexCoord0).xyz, 1.0);\n}\n\n\n", - "type": 36385 + "17ummFeJSrtyo7Ny+ynRfg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n}\n\n" }, - "AR5tabVvhA11kC/U8+LD5A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// directional_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n\n\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n \n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n", - "type": 36385 + "1fGQdakrI/l6BLcnFcIp+Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "AuDvf+lTpmEtd7/X6y6yNQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n\n\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n\n\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "1rsaUxw8y7WC59ipAoYd4w==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "CTvEG3OHHezvzTTLoMajSA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n\n\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "27ckrjp2miPxgJclleP5Jg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "DKWCTGOCULOBcnw4btkoeA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "2GBtYhe6qps7934dzbucbA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_downsampleDepthNormal.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nuniform sampler2D linearDepthMap;\nuniform sampler2D normalMap;\n\nin vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outLinearDepth;\nlayout(location = 1) out vec4 outNormal;\n\nvoid main(void) {\n // Gather 2 by 2 quads from texture and downsample\n\n // Try different filters for Z\n vec4 Zeyes = textureGather(linearDepthMap, varTexCoord0, 0);\n // float Zeye = texture(linearDepthMap, varTexCoord0).x;\n\n vec4 rawNormalsX = textureGather(normalMap, varTexCoord0, 0);\n vec4 rawNormalsY = textureGather(normalMap, varTexCoord0, 1);\n vec4 rawNormalsZ = textureGather(normalMap, varTexCoord0, 2);\n\n float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));\n\n vec3 normal = vec3(0.0);\n normal += unpackNormal(vec3(rawNormalsX[0], rawNormalsY[0], rawNormalsZ[0]));\n normal += unpackNormal(vec3(rawNormalsX[1], rawNormalsY[1], rawNormalsZ[1]));\n normal += unpackNormal(vec3(rawNormalsX[2], rawNormalsY[2], rawNormalsZ[2]));\n normal += unpackNormal(vec3(rawNormalsX[3], rawNormalsY[3], rawNormalsZ[3]));\n\n normal = normalize(normal);\n\n outLinearDepth = vec4(Zeye, 0.0, 0.0, 0.0);\n outNormal = vec4((normal + vec3(1.0)) * 0.5, 0.0);\n}\n\n\n\n" }, - "Db13N5hObKY6Kj1EjZFkTg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "2TRJ08daYh/TDKtgiJHRnQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// local_lights_drawOutline.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n Light lightArray[128];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n\n\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n\n\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n // Show edges\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n \n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n\n\n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n frag.position = fragPosition;\n\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragPos = invViewMat * fragPosition;\n \n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n _fragColor = vec4(0, 0, 0, 1);\n \n int numLightTouching = 0;\n int lightClusterOffset = cluster.z;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n vec3 color = vec3(0.0);\n if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 color = vec3(0.0);\n\n if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n}\n\n\n\n" }, - "Dt8fOWXGdtgAQToyFI9nnw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "2cHHDMdotyEYUK/0bGw5Yg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb + fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE + fadeEmissive,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n }\n}\n\n" }, - "Es83sm10YALNi31gEzX6AA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Tue May 22 11:51:57 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_transparent_textured_fade.slf\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n\n\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n\n\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float opacity = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n opacity = -_color.a;\n }\n\n\n opacity *= texel.a;\n vec3 albedo = _color.rgb * texel.rgb;\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n 1.0,\n fragPosition,\n fragNormal,\n albedo,\n DEFAULT_FRESNEL,\n 0.0f,\n fadeEmissive,\n DEFAULT_ROUGHNESS,\n opacity),\n opacity);\n\n}\n\n", - "type": 36385 + "3EPmuQdbeP4bvyeB9Ml2VQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += directionalSpecular / opacity;\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a * _alpha;\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" }, - "F65CV6x9s1o+jurvE3kC5A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Nissim Hadar on 9/5/2107.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n\n\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n\n\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nuniform sampler2D colorMap;\nuniform sampler2D linearDepthMap;\n\nvec4 unpackPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearDepthMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n if ((isHazeEnabled() == 0.0) || (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) {\n discard;\n }\n\n vec4 fragColor = texture(colorMap, varTexCoord0);\n vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);\n\n mat4 viewInverse = getViewInverse();\n vec4 fragPositionWS = viewInverse * fragPositionES;\n vec4 eyePositionWS = viewInverse[3];\n\n Light light = getKeyLight();\n vec3 lightDirectionWS = getLightDirection(light);\n\n outFragColor = computeHazeColor(fragColor, fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);\n}\n\n\n", - "type": 36385 + "3kmbrrZgeHWosgUewHePlw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += directionalSpecular / opacity;\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a * _alpha;\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" }, - "FiFtfEoms+yks+r9QAO6kw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model.slv\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// material_opaque_unlit.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nvoid main(void) {\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n", - "type": 36385 + "4/cBJggWTLzlkWDb3Cvryw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// standardTransformPNTC.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// standardDrawTexture.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/10/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// the texture\nuniform sampler2D colorMap;\n\nin vec3 varPosition;\nin vec3 varNormal;\nin vec2 varTexCoord0;\nin vec4 varColor;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n vec4 color = texture(colorMap, varTexCoord0);\n outFragColor = color * varColor;\n}\n\n\n" }, - "GAseYRZOa7I/+qpCNm0Q6w==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/30/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nfloat specularBeckmann(float ndoth, float roughness) {\n float alpha = acos(ndoth);\n float ta = tan(alpha);\n float val = 1.0 / (roughness * roughness * pow(ndoth, 4.0)) * exp(-(ta * ta) / (roughness * roughness));\n return val;\n}\n\nvoid main(void) {\n outFragColor = vec4(vec3(0.5 * pow( specularBeckmann(varTexCoord0.x, varTexCoord0.y), 0.1)), 1.0);\n}\n\n\n", - "type": 36385 + "43rQzjoR7m7l96PqypljMw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "GscuRMt2dhL2gYFo85KLgw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nfloat sRGBFloatToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n\n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 colorToLinearRGB(vec3 srgb) {\n return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));\n}\n\nvoid main(void) {\n outFragColor.a = 1.0;\n outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb);\n}\n\n", - "type": 36385 + "47eZoUUS5qAZqfH+ipeA0w==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "JJ4YIJR/MGdE8DTrF057EA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_transparent_textured_unlit.slf\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a);\n}\n\n", - "type": 36385 + "4i7CpQHClwhzhQ13dtFmww==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "LEdDqcYm/tJ+p8aIzI1N4A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n\n\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n\n\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "4zhj1JuoZvGR1LCXTOVenA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n}\n\n" }, - "LGFnF0PB1KRlexk9UUEAEw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// standardTransformPNTC.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// standardDrawTexture.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/10/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// the texture\nuniform sampler2D colorMap;\n\nin vec3 varPosition;\nin vec3 varNormal;\nin vec2 varTexCoord0;\nin vec4 varColor;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n vec4 color = texture(colorMap, varTexCoord0);\n outFragColor = color * varColor;\n}\n\n\n", - "type": 36385 + "58OO8MGSlS2k1Qn10mamwQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "M7iRK3FjJwABFG/YF9EyZw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) out vec4 _fragColor;\n\nin vec4 _positionWS;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "5bcd/ODHdGbVBs/F+T2X8A==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// material_opaque_unlit.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\nlayout(location = 5) in float _alpha;\n\nvoid main(void) {\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n" }, - "MJKy4tDJvhVf7/13YJGTBg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model.slv\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// overlay3D.slf\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\n\n\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n\n vec3 fragPosition = _positionES.xyz;\n\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalSkyboxGlobalColor(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n roughness),\n opacity);\n\n // And emissive\n color.rgb += emissive * isEmissiveEnabled();\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n", - "type": 36385 + "5iiY0vIxLsCSpgiFabIarw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\nlayout(location = 6) in float _alpha;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n" }, - "MlywjkT1O3yVFfPvi0rTjg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "5l+NrW5M5EYQwM35VGiwnQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// forward_simple_textured_transparent.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n\n\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n\n\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n\n\n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n // FIXME - temporarily removed until we support it for forward...\n /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }*/\n\n return color;\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nlayout(location = 0) in vec3 _normalWS;\nlayout(location = 1) in vec4 _color;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec4 _positionES;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n TransformCamera cam = getTransformCamera();\n vec3 fragPosition = _positionES.xyz;\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n DEFAULT_OCCLUSION,\n fragPosition,\n normalize(_normalWS),\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_ROUGHNESS, colorAlpha),\n colorAlpha);\n}\n\n" }, - "Nk9PhvKwxIxJ684bn5Y5aw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model.slv\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// overlay3D_model_transparent.slf\n//\n// Created by Sam Gateau on 2/27/2017.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n\n\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPosition = _positionES.xyz;\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n emissive,\n roughness, opacity),\n opacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n", - "type": 36385 + "6jeBT9ZR8yCpxEdAcd36xA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// local_lights_drawOutline.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n Light lightArray[128];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n\n\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n\n\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n // Show edges\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nbool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir) {\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n \n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n color = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n\n return (edge < 1.0);\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n\n\n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n frag.position = fragPosition;\n\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragPos = invViewMat * fragPosition;\n \n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n _fragColor = vec4(0, 0, 0, 1);\n \n int numLightTouching = 0;\n int lightClusterOffset = cluster.z;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n vec3 color = vec3(0.0);\n if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 color = vec3(0.0);\n\n if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) {\n _fragColor.rgb += color;\n }\n }\n\n}\n\n\n\n" }, - "Q/5RNubBTK1E3RMhhVzqXg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n", - "type": 36385 + "6m/vijX36wYDyY83TmJybg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Sat Oct 24 09:34:37 2015\n//\n// toneMapping.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct ToneMappingParams {\n vec4 _exp_2powExp_s0_s1;\n ivec4 _toneCurve_s0_s1_s2;\n};\n\nconst float INV_GAMMA_22 = 1.0 / 2.2;\nconst int ToneCurveNone = 0;\nconst int ToneCurveGamma22 = 1;\nconst int ToneCurveReinhard = 2;\nconst int ToneCurveFilmic = 3;\n\nuniform toneMappingParamsBuffer {\n ToneMappingParams params;\n};\nfloat getTwoPowExposure() {\n return params._exp_2powExp_s0_s1.y;\n}\nint getToneCurve() {\n return params._toneCurve_s0_s1_s2.x;\n}\n\nuniform sampler2D colorMap;\n \nin vec2 varTexCoord0;\nout vec4 outFragColor;\n \nvoid main(void) {\n vec4 fragColorRaw = texture(colorMap, varTexCoord0);\n vec3 fragColor = fragColorRaw.xyz;\n\n vec3 srcColor = fragColor * getTwoPowExposure();\n\n int toneCurve = getToneCurve();\n vec3 tonedColor = srcColor;\n if (toneCurve == ToneCurveFilmic) {\n vec3 x = max(vec3(0.0), srcColor-0.004);\n tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);\n } else if (toneCurve == ToneCurveReinhard) {\n tonedColor = srcColor/(1.0 + srcColor);\n tonedColor = pow(tonedColor, vec3(INV_GAMMA_22));\n } else if (toneCurve == ToneCurveGamma22) {\n tonedColor = pow(srcColor, vec3(INV_GAMMA_22));\n } // else None toned = src\n\n outFragColor = vec4(tonedColor, 1.0);\n}\n\n\n" }, - "QGR2ZsQ//YYBGDT5PTVTaw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:52:00 2018\n//\n// taa.frag\n// fragment shader\n//\n// Created by Sam Gateau on 8/14/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// Generated on Tue May 22 11:52:00 2018\n//\n// TAA.slh\n// Common component needed by TemporalAntialiasing fragment shader\n//\n// Created by Sam Gateau on 8/17/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nuniform sampler2D depthMap;\nuniform sampler2D sourceMap;\nuniform sampler2D historyMap;\nuniform sampler2D velocityMap;\nuniform sampler2D nextMap;\n\nstruct TAAParams\n{\n\tfloat none;\n\tfloat blend;\n\tfloat covarianceGamma;\n\tfloat debugShowVelocityThreshold;\n ivec4 flags;\n vec4 pixelInfo_orbZoom;\n vec4 regionInfo;\n};\n\nlayout(std140) uniform taaParamsBuffer {\n TAAParams params;\n};\n\n#define GET_BIT(bitfield, bitIndex) bool((bitfield) & (1 << (bitIndex)))\n\nbool taa_isDebugEnabled() {\n return GET_BIT(params.flags.x, 0);\n}\n\nbool taa_showDebugCursor() {\n return GET_BIT(params.flags.x, 1);\n}\n\nbool taa_showClosestFragment() {\n return GET_BIT(params.flags.x, 3);\n}\n\nbool taa_constrainColor() {\n return GET_BIT(params.flags.y, 1);\n}\n\nbool taa_feedbackColor() {\n return GET_BIT(params.flags.y, 4);\n}\n\nvec2 taa_getDebugCursorTexcoord() {\n return params.pixelInfo_orbZoom.xy;\n}\n\nfloat taa_getDebugOrbZoom() {\n return params.pixelInfo_orbZoom.z;\n}\n\nvec2 taa_getRegionDebug() {\n return params.regionInfo.xy;\n}\n\nvec2 taa_getRegionFXAA() {\n return params.regionInfo.zw;\n}\n#define USE_YCOCG 1\n\nvec4 taa_fetchColor(sampler2D map, vec2 uv) {\n\tvec4 c = texture(map, uv);\n\t// Apply rapid pseudo tonemapping as TAA is applied to a tonemapped image, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),c.rgb);\n\tc.rgb = c.rgb / (1.0+lum);\n#if USE_YCOCG\n\treturn vec4(color_LinearToYCoCg(c.rgb), c.a);\n#else\n\treturn c;\n#endif\n}\n\nvec3 taa_resolveColor(vec3 color) {\n#if USE_YCOCG\n\tcolor = max(vec3(0), color_YCoCgToUnclampedLinear(color));\n#endif\n\t// Apply rapid inverse tonemapping, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),color.rgb);\n\tcolor = color / (1.0-lum);\n\treturn color;\n}\n\nvec4 taa_fetchSourceMap(vec2 uv) {\n\treturn taa_fetchColor(sourceMap, uv);\n}\n\nvec4 taa_fetchHistoryMap(vec2 uv) {\n\treturn taa_fetchColor(historyMap, uv);\n}\n\nvec4 taa_fetchNextMap(vec2 uv) {\n\treturn taa_fetchColor(nextMap, uv);\n}\n\nvec2 taa_fetchVelocityMap(vec2 uv) {\n\treturn texture(velocityMap, uv).xy;\n}\n\nfloat taa_fetchDepth(vec2 uv) {\n\treturn -texture(depthMap, vec2(uv), 0).x;\n}\n\n\n#define ZCMP_GT(a, b) (a > b)\n\nvec2 taa_getImageSize() {\n vec2 imageSize = getWidthHeight(0);\n if (isStereo()) {\n imageSize.x *= 2.0;\n }\n return imageSize;\n}\n\nvec2 taa_getTexelSize() {\n vec2 texelSize = getInvWidthHeight();\n if (isStereo()) {\n texelSize.x *= 0.5;\n }\n return texelSize;\n}\n\nvec3 taa_findClosestFragment3x3(vec2 uv)\n{\n\tvec2 dd = abs(taa_getTexelSize());\n\tvec2 du = vec2(dd.x, 0.0);\n\tvec2 dv = vec2(0.0, dd.y);\n\n\tvec3 dtl = vec3(-1, -1, taa_fetchDepth(uv - dv - du));\n\tvec3 dtc = vec3( 0, -1, taa_fetchDepth(uv - dv));\n\tvec3 dtr = vec3( 1, -1, taa_fetchDepth(uv - dv + du));\n\n\tvec3 dml = vec3(-1, 0, taa_fetchDepth(uv - du));\n\tvec3 dmc = vec3( 0, 0, taa_fetchDepth(uv));\n\tvec3 dmr = vec3( 1, 0, taa_fetchDepth(uv + du));\n\n\tvec3 dbl = vec3(-1, 1, taa_fetchDepth(uv + dv - du));\n\tvec3 dbc = vec3( 0, 1, taa_fetchDepth(uv + dv));\n\tvec3 dbr = vec3( 1, 1, taa_fetchDepth(uv + dv + du));\n\n\tvec3 dmin = dtl;\n\tif (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc;\n\tif (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr;\n\n\tif (ZCMP_GT(dmin.z, dml.z)) dmin = dml;\n\tif (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc;\n\tif (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr;\n\n\tif (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl;\n\tif (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc;\n\n\n\tif (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr;\n\n\treturn vec3(uv + dd.xy * dmin.xy, dmin.z);\n}\n\nvec2 taa_fetchVelocityMapBest(vec2 uv) {\n vec2 dd = abs(taa_getTexelSize());\n vec2 du = vec2(dd.x, 0.0);\n vec2 dv = vec2(0.0, dd.y);\n\n vec2 dtl = taa_fetchVelocityMap(uv - dv - du);\n vec2 dtc = taa_fetchVelocityMap(uv - dv);\n vec2 dtr = taa_fetchVelocityMap(uv - dv + du);\n\n vec2 dml = taa_fetchVelocityMap(uv - du);\n vec2 dmc = taa_fetchVelocityMap(uv);\n vec2 dmr = taa_fetchVelocityMap(uv + du);\n\n vec2 dbl = taa_fetchVelocityMap(uv + dv - du);\n vec2 dbc = taa_fetchVelocityMap(uv + dv);\n vec2 dbr = taa_fetchVelocityMap(uv + dv + du);\n\n vec3 best = vec3(dtl, dot(dtl,dtl));\n\n float testSpeed = dot(dtc,dtc);\n if (testSpeed > best.z) { best = vec3(dtc, testSpeed); }\n testSpeed = dot(dtr,dtr);\n if (testSpeed > best.z) { best = vec3(dtr, testSpeed); }\n\n testSpeed = dot(dml,dml);\n if (testSpeed > best.z) { best = vec3(dml, testSpeed); }\n testSpeed = dot(dmc,dmc);\n if (testSpeed > best.z) { best = vec3(dmc, testSpeed); }\n testSpeed = dot(dmr,dmr);\n if (testSpeed > best.z) { best = vec3(dmr, testSpeed); }\n\n testSpeed = dot(dbl,dbl);\n if (testSpeed > best.z) { best = vec3(dbl, testSpeed); }\n testSpeed = dot(dbc,dbc);\n if (testSpeed > best.z) { best = vec3(dbc, testSpeed); }\n testSpeed = dot(dbr,dbr);\n if (testSpeed > best.z) { best = vec3(dbr, testSpeed); }\n\n return best.xy;\n}\n\nvec2 taa_fromFragUVToEyeUVAndSide(vec2 fragUV, out int stereoSide) {\n vec2 eyeUV = fragUV;\n stereoSide = 0;\n if (isStereo()) {\n if (eyeUV.x > 0.5) {\n eyeUV.x -= 0.5;\n stereoSide = 1;\n }\n eyeUV.x *= 2.0;\n }\n return eyeUV;\n}\n\nvec2 taa_fromEyeUVToFragUV(vec2 eyeUV, int stereoSide) {\n vec2 fragUV = eyeUV;\n if (isStereo()) {\n fragUV.x *= 0.5;\n fragUV.x += stereoSide*0.5;\n }\n return fragUV;\n}\n\nvec2 taa_computePrevFragAndEyeUV(vec2 fragUV, vec2 fragVelocity, out vec2 prevEyeUV) {\n int stereoSide = 0;\n vec2 eyeUV = taa_fromFragUVToEyeUVAndSide(fragUV, stereoSide);\n prevEyeUV = eyeUV - fragVelocity;\n return taa_fromEyeUVToFragUV(prevEyeUV, stereoSide);\n}\n\nvec2 taa_fetchSourceAndHistory(vec2 fragUV, vec2 fragVelocity, out vec3 sourceColor, out vec3 historyColor) {\n vec2 prevEyeUV;\n vec2 prevFragUV = taa_computePrevFragAndEyeUV(fragUV, fragVelocity, prevEyeUV);\n sourceColor = taa_fetchSourceMap(fragUV).xyz;\n\n historyColor = sourceColor;\n if (!(any(lessThan(prevEyeUV, vec2(0.0))) || any(greaterThan(prevEyeUV, vec2(1.0))))) {\n historyColor = taa_fetchHistoryMap(prevFragUV).xyz;\n }\n return prevFragUV;\n}\n\nfloat Luminance(vec3 rgb) {\n return rgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0;\n}\n\n#define MINMAX_3X3_ROUNDED 1\n\nmat3 taa_evalNeighbourColorVariance(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity) {\n vec2 texelSize = taa_getTexelSize();\n \n\n\tvec2 du = vec2(texelSize.x, 0.0);\n\tvec2 dv = vec2(0.0, texelSize.y);\n\n vec3 sampleColor = taa_fetchSourceMap(fragUV - dv - du).rgb;\n vec3 sumSamples = sampleColor;\n vec3 sumSamples2 = sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sampleColor isn't it ?\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n \n sampleColor = taa_fetchSourceMap(fragUV + dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n \n vec3 mu = sumSamples / vec3(9.0);\n vec3 sigma = sqrt(max(sumSamples2 / vec3(9.0) - mu * mu, vec3(0.0)));\n \n float gamma = params.covarianceGamma;\n vec3 cmin = mu - gamma * sigma;\n vec3 cmax = mu + gamma * sigma;\n\n return mat3(cmin, cmax, mu);\n}\n\nmat3 taa_evalNeighbourColorRegion(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity, float fragZe) {\n vec2 imageSize = taa_getImageSize();\n vec2 texelSize = taa_getTexelSize();\n vec3 cmin, cmax, cavg;\n\n #if MINMAX_3X3_ROUNDED\n\t\tvec2 du = vec2(texelSize.x, 0.0);\n\t\tvec2 dv = vec2(0.0, texelSize.y);\n\n\t\tvec3 ctl = taa_fetchSourceMap(fragUV - dv - du).rgb;\n\t\tvec3 ctc = taa_fetchSourceMap(fragUV - dv).rgb;\n\t\tvec3 ctr = taa_fetchSourceMap(fragUV - dv + du).rgb;\n\t\tvec3 cml = taa_fetchSourceMap(fragUV - du).rgb;\n\t\tvec3 cmc = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sample isn't it ?\n\t\tvec3 cmr = taa_fetchSourceMap(fragUV + du).rgb;\n\t\tvec3 cbl = taa_fetchSourceMap(fragUV + dv - du).rgb;\n\t\tvec3 cbc = taa_fetchSourceMap(fragUV + dv).rgb;\n\t\tvec3 cbr = taa_fetchSourceMap(fragUV + dv + du).rgb;\n\n\t\tcmin = min(ctl, min(ctc, min(ctr, min(cml, min(cmc, min(cmr, min(cbl, min(cbc, cbr))))))));\n\t\tcmax = max(ctl, max(ctc, max(ctr, max(cml, max(cmc, max(cmr, max(cbl, max(cbc, cbr))))))));\n\n\t\t#if MINMAX_3X3_ROUNDED || USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (ctl + ctc + ctr + cml + cmc + cmr + cbl + cbc + cbr) / 9.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n\n\t\t#if MINMAX_3X3_ROUNDED\n\t\t\tvec3 cmin5 = min(ctc, min(cml, min(cmc, min(cmr, cbc))));\n\t\t\tvec3 cmax5 = max(ctc, max(cml, max(cmc, max(cmr, cbc))));\n\t\t\tvec3 cavg5 = (ctc + cml + cmc + cmr + cbc) / 5.0;\n\t\t\tcmin = 0.5 * (cmin + cmin5);\n\t\t\tcmax = 0.5 * (cmax + cmax5);\n\t\t\tcavg = 0.5 * (cavg + cavg5);\n\t\t#endif\n #else\n\t\tconst float _SubpixelThreshold = 0.5;\n\t\tconst float _GatherBase = 0.5;\n\t\tconst float _GatherSubpixelMotion = 0.1666;\n\n\t\tvec2 texel_vel = fragVelocity * imageSize;\n\t\tfloat texel_vel_mag = length(texel_vel) * -fragZe;\n\t\tfloat k_subpixel_motion = clamp(_SubpixelThreshold / (0.0001 + texel_vel_mag), 0.0, 1.0);\n\t\tfloat k_min_max_support = _GatherBase + _GatherSubpixelMotion * k_subpixel_motion;\n\n\t\tvec2 ss_offset01 = k_min_max_support * vec2(-texelSize.x, texelSize.y);\n\t\tvec2 ss_offset11 = k_min_max_support * vec2(texelSize.x, texelSize.y);\n\t\tvec3 c00 = taa_fetchSourceMap(fragUV - ss_offset11).rgb;\n\t\tvec3 c10 = taa_fetchSourceMap(fragUV - ss_offset01).rgb;\n\t\tvec3 c01 = taa_fetchSourceMap(fragUV + ss_offset01).rgb;\n\t\tvec3 c11 = taa_fetchSourceMap(fragUV + ss_offset11).rgb;\n\n\t\tcmin = min(c00, min(c10, min(c01, c11)));\n\t\tcmax = max(c00, max(c10, max(c01, c11)));\n cavg = (cmin + cmax ) * 0.5;\n\n\t\t#if USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (c00 + c10 + c01 + c11) / 4.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n #endif\n\n \t\t// shrink chroma min-max\n\t#if USE_YCOCG\n\t\tvec2 chroma_extent = vec2(0.25 * 0.5 * (cmax.r - cmin.r));\n\t\tvec2 chroma_center = sourceColor.gb;\n\t\tcmin.yz = chroma_center - chroma_extent;\n\t\tcmax.yz = chroma_center + chroma_extent;\n\t\tcavg.yz = chroma_center;\n\t#endif\n\n return mat3(cmin, cmax, cavg);\n}\n\n//#define USE_OPTIMIZATIONS 0\n\nvec3 taa_clampColor(vec3 colorMin, vec3 colorMax, vec3 colorSource, vec3 color) {\n\tconst float eps = 0.00001;\n vec3 p = colorSource;\n vec3 q = color;\n\t// note: only clips towards aabb center (but fast!)\n\tvec3 p_clip = 0.5 * (colorMax + colorMin);\n\tvec3 e_clip = 0.5 * (colorMax - colorMin) + vec3(eps);\n\n\tvec3 v_clip = q - p_clip;\n\tvec3 v_unit = v_clip.xyz / e_clip;\n\tvec3 a_unit = abs(v_unit);\n\tfloat ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z));\n\n\tif (ma_unit > 1.0)\n\t\treturn p_clip + v_clip / ma_unit;\n\telse\n\t\treturn q;// point inside aabb\t\t\n}\n\nvec3 taa_evalConstrainColor(vec3 sourceColor, vec2 sourceUV, vec2 sourceVel, vec3 candidateColor) {\n mat3 colorMinMaxAvg;\n\n colorMinMaxAvg = taa_evalNeighbourColorVariance(sourceColor, sourceUV, sourceVel);\n \n\t// clamp history to neighbourhood of current sample\n return taa_clampColor(colorMinMaxAvg[0], colorMinMaxAvg[1], sourceColor, candidateColor);\n}\n\nvec3 taa_evalFeedbackColor(vec3 sourceColor, vec3 historyColor, float blendFactor) {\n const float _FeedbackMin = 0.1;\n const float _FeedbackMax = 0.9;\n\t// feedback weight from unbiased luminance diff (t.lottes)\n\t#if USE_YCOCG\n\t\tfloat lum0 = sourceColor.r;\n\t\tfloat lum1 = historyColor.r;\n\t#else\n\t\tfloat lum0 = Luminance(sourceColor.rgb);\n\t\tfloat lum1 = Luminance(historyColor.rgb);\n\t#endif\n\tfloat unbiased_diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));\n\tfloat unbiased_weight = 1.0 - unbiased_diff;\n\tfloat unbiased_weight_sqr = unbiased_weight * unbiased_weight;\n\tfloat k_feedback = mix(_FeedbackMin, _FeedbackMax, unbiased_weight_sqr);\n\n \n vec3 nextColor = mix(historyColor, sourceColor, k_feedback * blendFactor).xyz;\n return nextColor;\n}\n\n\nvec3 colorWheel(float normalizedHue) {\n float v = normalizedHue * 6.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n } else if (v < 2.f) {\n return vec3(1.f - (v-1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v-2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v-3.f), 1.f );\n } else if (v < 5.f) {\n return vec3((v-4.f), 0.f, 1.f );\n } else if (v < 6.f) {\n return vec3(1.f, 0.f, 1.f - (v-5.f));\n } else {\n return vec3(1.f, 0.f, 0.f);\n }\n}\n\nvec3 colorRamp(float normalizedHue) {\n float v = normalizedHue * 5.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n\n\n } else if (v < 2.f) {\n return vec3(1.f - (v - 1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v - 2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v - 3.f), 1.f);\n } else if (v < 5.f) {\n return vec3((v - 4.f), 0.f, 1.f);\n } else {\n return vec3(1.f, 0.f, 1.f);\n }\n}\n\n\nvec3 taa_getVelocityColorRelative(float velocityPixLength) {\n return colorRamp(velocityPixLength/params.debugShowVelocityThreshold);\n}\n\nvec3 taa_getVelocityColorAboveThreshold(float velocityPixLength) {\n return colorRamp((velocityPixLength - params.debugShowVelocityThreshold)/params.debugShowVelocityThreshold);\n}\n\n\nvec3 taa_evalFXAA(vec2 fragUV) {\n\n // vec2 texelSize = getInvWidthHeight();\n vec2 texelSize = taa_getTexelSize();\n\n // filter width limit for dependent \"two-tap\" texture samples\n float FXAA_SPAN_MAX = 8.0;\n\n // local contrast multiplier for performing AA\n // higher = sharper, but setting this value too high will cause near-vertical and near-horizontal edges to fail\n // see \"fxaaQualityEdgeThreshold\"\n float FXAA_REDUCE_MUL = 1.0 / 8.0;\n\n // luminance threshold for processing dark colors\n // see \"fxaaQualityEdgeThresholdMin\"\n float FXAA_REDUCE_MIN = 1.0 / 128.0;\n\n // fetch raw RGB values for nearby locations\n // sampling pattern is \"five on a die\" (each diagonal direction and the center)\n // computing the coordinates for these texture reads could be moved to the vertex shader for speed if needed\n vec3 rgbNW = texture(sourceMap, fragUV + (vec2(-1.0, -1.0) * texelSize)).xyz;\n vec3 rgbNE = texture(sourceMap, fragUV + (vec2(+1.0, -1.0) * texelSize)).xyz;\n vec3 rgbSW = texture(sourceMap, fragUV + (vec2(-1.0, +1.0) * texelSize)).xyz;\n vec3 rgbSE = texture(sourceMap, fragUV + (vec2(+1.0, +1.0) * texelSize)).xyz;\n vec3 rgbM = texture(sourceMap, fragUV).xyz;\n\t\n // convert RGB values to luminance\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot( rgbM, luma);\n\t\n // luma range of local neighborhood\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\t\n // direction perpendicular to local luma gradient\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n // compute clamped direction offset for additional \"two-tap\" samples\n // longer vector = blurry, shorter vector = sharp\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), \n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize;\n\t\t\n // perform additional texture sampling perpendicular to gradient\n vec3 rgbA = (1.0 / 2.0) * (\n texture(sourceMap, fragUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (\n texture(sourceMap, fragUV + dir * (0.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (3.0 / 3.0 - 0.5)).xyz);\n float lumaB = dot(rgbB, luma);\n\n // compare luma of new samples to the luma range of the original neighborhood\n // if the new samples exceed this range, just use the first two samples instead of all four\n if (lumaB < lumaMin || lumaB > lumaMax) {\n return rgbA;\n } else {\n return rgbB;\n }\n}in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main() {\n vec2 fragUV = varTexCoord0;\n\n // Debug region before debug or fxaa region X\n float distToRegionFXAA = fragUV.x - taa_getRegionFXAA().x; \n if (distToRegionFXAA > 0.0) {\n outFragColor = vec4(taa_evalFXAA(fragUV), 1.0);\n return;\n }\n\n vec2 fragVel = taa_fetchVelocityMapBest(fragUV).xy;\n\n vec3 sourceColor;\n vec3 historyColor;\n vec2 prevFragUV = taa_fetchSourceAndHistory(fragUV, fragVel, sourceColor, historyColor);\n\n vec3 nextColor = sourceColor;\n \n if (taa_constrainColor()) {\n // clamp history to neighbourhood of current sample\n historyColor = taa_evalConstrainColor(sourceColor, fragUV, fragVel, historyColor);\n }\n \n if (taa_feedbackColor()) {\n nextColor = taa_evalFeedbackColor(sourceColor, historyColor, params.blend);\n } else {\n nextColor = mix(historyColor, sourceColor, params.blend);\n }\n\n outFragColor = vec4(taa_resolveColor(nextColor), 1.0);\n}\n\n\n", - "type": 36385 + "7FNQjpsWLg0f0vQMLCi6Wg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// fxaa_blend.frag\n// fragment shader\n//\n// Created by Raffi Bedikian on 8/30/15\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D colorTexture;\nuniform float sharpenIntensity;\n\nvoid main(void) {\n vec4 pixels[9];\n vec4 sharpenedPixel;\n pixels[0] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,-1), 0);\n pixels[1] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,-1), 0);\n pixels[2] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,-1), 0);\n\n pixels[3] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,0), 0);\n pixels[4] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), 0);\n pixels[5] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,0), 0);\n\n pixels[6] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,1), 0);\n\n\n pixels[7] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0);\n pixels[8] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,1), 0);\n\n sharpenedPixel = pixels[4]*6.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;\n\n\tvec4 minColor = max(vec4(0), pixels[4]-vec4(0.5));\n\tvec4 maxColor = pixels[4]+vec4(0.5);\n outFragColor = clamp(pixels[4] + sharpenedPixel * sharpenIntensity, minColor, maxColor);\n}\n\n\n" }, - "QTILTXQILSlOwbTKce1vzg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// fxaa_blend.frag\n// fragment shader\n//\n// Created by Raffi Bedikian on 8/30/15\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D colorTexture;\nuniform float sharpenIntensity;\n\nvoid main(void) {\n vec4 pixels[9];\n vec4 sharpenedPixel;\n pixels[0] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,-1), 0);\n pixels[1] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,-1), 0);\n pixels[2] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,-1), 0);\n\n pixels[3] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,0), 0);\n pixels[4] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), 0);\n pixels[5] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,0), 0);\n\n pixels[6] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,1), 0);\n\n\n pixels[7] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0);\n pixels[8] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,1), 0);\n\n sharpenedPixel = pixels[4]*6.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;\n\n\tvec4 minColor = max(vec4(0), pixels[4]-vec4(0.5));\n\tvec4 maxColor = pixels[4]+vec4(0.5);\n outFragColor = clamp(pixels[4] + sharpenedPixel * sharpenIntensity, minColor, maxColor);\n}\n\n\n", - "type": 36385 + "7IV5hopxBctOtJIAvRJeZw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent_normal_map.vert\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "QwnIDLO+gE/HOXiOm/hSvg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:52:00 2018\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D depthMap;\n\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n \n\tfloat Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n\n\t// The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalUnjitteredEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);\n\tvec3 worldPos = (getViewInverse() * vec4(eyePos, 1.0)).xyz;\n \n vec3 prevEyePos = (getPreviousView() * vec4(worldPos, 1.0)).xyz;\n vec4 prevClipPos = (getUnjitteredProjection(stereoSide.x) * vec4(prevEyePos, 1.0));\n vec2 prevUV = 0.5 * (prevClipPos.xy / prevClipPos.w) + vec2(0.5);\n\n //vec2 imageSize = getWidthHeight(0);\n vec2 imageSize = vec2(1.0, 1.0);\n outFragColor = vec4( ((texcoordPos - prevUV) * imageSize), 0.0, 0.0);\n}\n\n\n", - "type": 36385 + "7bsWJwqr6TCCCD7GT/odNw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb + fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE + fadeEmissive,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n }\n}\n\n" }, - "S1/PA6woTFAa1y/a29RGqQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// sdf_text3D.vert\n// vertex shader\n//\n// Created by Brad Davis on 10/14/13.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec2 _texCoord0;\n\nvoid main() {\n _texCoord0 = inTexCoord0.xy;\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n const vec3 normal = vec3(0, 0, 1);\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, normal), dot(mr1, normal), dot(mr2, normal));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// sdf_text3D.frag\n// fragment shader\n//\n// Created by Bradley Austin Davis on 2015-02-04\n// Based on fragment shader code from \n// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp \n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n\n\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\nuniform sampler2D Font;\nuniform bool Outline;\nuniform vec4 Color;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec2 _texCoord0;\n\n#define TAA_TEXTURE_LOD_BIAS -3.0\n\nconst float interiorCutoff = 0.8;\nconst float outlineExpansion = 0.2;\nconst float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);\n\nfloat evalSDF(vec2 texCoord) {\n // retrieve signed distance\n float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;\n if (Outline) {\n if (sdf > interiorCutoff) {\n sdf = 1.0 - sdf;\n } else {\n sdf += outlineExpansion;\n }\n }\n // Rely on TAA for anti-aliasing\n return step(0.5, sdf);\n}\n\nvoid main() {\n\n\n vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias;\n vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias;\n\n\t// Perform 4x supersampling for anisotropic filtering\n float a;\n\ta = evalSDF(_texCoord0);\n\ta += evalSDF(_texCoord0+dxTexCoord);\n\ta += evalSDF(_texCoord0+dyTexCoord);\n\ta += evalSDF(_texCoord0+dxTexCoord+dyTexCoord);\n a *= 0.25;\n\n // discard if invisible\n if (a < 0.01) {\n discard;\n }\n\n packDeferredFragment(\n normalize(_normalWS),\n a * Color.a,\n Color.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n}\n\n", - "type": 36385 + "7clizhBrq2Q7sao4iat75A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "SPfIGpsR/hSCwwhUfpS2JQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// directional_skybox_light.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/8/2015.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n", - "type": 36385 + "7rT0hub5yYofFRvlIiiWgw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n\n// OpenGLDisplayPlugin_present.frag\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nfloat sRGBFloatToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n\n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 colorToLinearRGB(vec3 srgb) {\n return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));\n}\n\nvoid main(void) {\n outFragColor.a = 1.0;\n outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb);\n}\n\n" }, - "T4goBpLzzr7EM2moN8GBRQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) out vec4 _fragColor;\n\nin vec4 _positionWS;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "7wSgkilDDLl77uiwvnvqbA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb+fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb+fadeEmissive);\n }\n}\n\n" }, - "TcLzUOvCrV2zfLfxVKv7Ig==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\nvec3 integrate(float cosTheta, float skinRadius) {\n // Angle from lighting direction.\n float theta = acos(cosTheta);\n vec3 totalWeights = vec3(0.0);\n vec3 totalLight = vec3(0.0);\n\n const float _PI = 3.14159265358979523846;\n const float step = 2.0 * _PI / float(2000);\n float a = -(_PI);\n\n\n while (a <= (_PI)) {\n float sampleAngle = theta + a;\n float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);\n //if (diffuse < 0.0) diffuse = 0.0;\n //if (diffuse > 1.0) diffuse = 1.0;\n\n // Distance.\n float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5));\n\n // Profile Weight.\n vec3 weights = scatter(sampleDist);\n\n totalWeights += weights;\n totalLight += diffuse * weights;\n a += step;\n }\n\n vec3 result = (totalLight / totalWeights);\n return clamp(result, vec3(0.0), vec3(1.0));\n\n}\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n\n // Lookup by: x: NDotL y: 1 / r\n //float y = 2.0 * 1.0 / ((j + 1.0) / (double)height);\n //float x = ((i / (double)width) * 2.0) - 1.0;\n\n outFragColor = vec4(integrate(varTexCoord0.x * 2.0 - 1.0, 2.0 / varTexCoord0.y), 1.0);\n}\n\n\n\n", - "type": 36385 + "9UNlgMJxCPmCgXyqfgXC/w==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// skin_model_shadow_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "TiJvHXCQ8RS/YznFW3J5BQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\n\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "9bKFfOQuaMZsiHJwa80zAA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n\n\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "Tz73oEH7CGpp2gTxxxOKNQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "9nR6MFNx+/46oTyCg6ThIQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "VEVUMO8DI8oliq3gjvdSAA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// overlay3D.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// overlay3D_translucent.slf\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += directionalSpecular / opacity;\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a * _alpha;\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n", - "type": 36385 + "9x28Xrw/xEV/kVPwTv9CHA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTransformUnitQuad.vert\n// \n// Draw and transform the unit quad [-1,-1 -> 1,1]\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * pos);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTexture.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n" }, - "VJRjSEMivaNWuHZWV3Oxrg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_opaque_web_browser.slf\n// fragment shader\n//\n// Created by Anthony Thibault on 7/25/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n texel = color_sRGBAToLinear(texel);\n packDeferredFragmentUnlit(normalize(_normalWS), 1.0, _color.rgb * texel.rgb);\n}\n\n\n", - "type": 36385 + "ACXHB/kbeWO+idEVbQjvtg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb+fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb+fadeEmissive);\n }\n}\n\n" }, - "VLdO/nTffRVo1OB/Gi9jPQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "BKlbpHIbPaLybLfXXSdJKA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// local_lights_shading.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n\n\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n\n\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n\n\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}in vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n _fragColor = vec4(0.0);\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n\n\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord);\n vec4 fragPosition = frag.position;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragWorldPos = invViewMat * fragPosition;\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);\n }\n\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir);\n\n _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface, \n frag.metallic, frag.fresnel, frag.albedo, frag.scattering, \n midNormalCurvature, lowNormalCurvature, 1.0);\n\n}\n\n\n\n" }, - "Wo3Or5sK/YMDimLw15SBFg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n\n\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "BQ83agynx1cQM79Nsh7vsQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "XCw45KRycsF8D11Mc5mtZQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_transparent_textured.slf\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n}\n\n", - "type": 36385 + "BjT/P1Q1JvAhSaNy0pqssQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "XlGvxXKk256llLH8bT2vWg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "Bxa7+GW9Fehb86BlWiNoDQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n if (albedo.a <= 0.1) {\n discard;\n }\n vec4 color = vec4(albedo.rgb * _color, albedo.a);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" }, - "Xpu0F5svGrEaOI/qlXpM9A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model.slv\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\n\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "C/+VdBtAvRrtzYuIEm4KIQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n\n\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n" }, - "XrTJWwv8Ufr0xLMVFg5FvA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n\n\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "CBCkoDtHdxwMHRDjxHBTgg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_downsampleDepthNormal.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nuniform sampler2D linearDepthMap;\nuniform sampler2D normalMap;\n\nin vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outLinearDepth;\nlayout(location = 1) out vec4 outNormal;\n\nvoid main(void) {\n // Gather 2 by 2 quads from texture and downsample\n\n // Try different filters for Z\n vec4 Zeyes = textureGather(linearDepthMap, varTexCoord0, 0);\n // float Zeye = texture(linearDepthMap, varTexCoord0).x;\n\n vec4 rawNormalsX = textureGather(normalMap, varTexCoord0, 0);\n vec4 rawNormalsY = textureGather(normalMap, varTexCoord0, 1);\n vec4 rawNormalsZ = textureGather(normalMap, varTexCoord0, 2);\n\n float Zeye = min(min(Zeyes.x, Zeyes.y), min(Zeyes.z, Zeyes.w));\n\n vec3 normal = vec3(0.0);\n normal += unpackNormal(vec3(rawNormalsX[0], rawNormalsY[0], rawNormalsZ[0]));\n normal += unpackNormal(vec3(rawNormalsX[1], rawNormalsY[1], rawNormalsZ[1]));\n normal += unpackNormal(vec3(rawNormalsX[2], rawNormalsY[2], rawNormalsZ[2]));\n normal += unpackNormal(vec3(rawNormalsX[3], rawNormalsY[3], rawNormalsZ[3]));\n\n normal = normalize(normal);\n\n outLinearDepth = vec4(Zeye, 0.0, 0.0, 0.0);\n outNormal = vec4((normal + vec3(1.0)) * 0.5, 0.0);\n}\n\n\n\n" }, - "YAcgE4Qfuss4WXKUXFb1QA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/27/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\n\nvec3 generateProfile(vec2 uv) {\n return scatter(uv.x * 2.0);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(generateProfile(varTexCoord0.xy), 1.0);\n}\n\n\n", - "type": 36385 + "CKRCiOl6f0gS65/2JDZnNA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:38 2018\n// skybox.vert\n// vertex shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec3 _normal;\n\nvoid main(void) {\n const float depth = 0.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 inPosition = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n vec3 clipDir = vec3(inPosition.xy, 0.0);\n vec3 eyeDir;\n { // transformClipToEyeDir\n eyeDir = vec3(cam._projectionInverse * vec4(clipDir.xyz, 1.0)); // Must be 1.0 here\n }\n\n { // transformEyeToWorldDir\n _normal = vec3(cam._viewInverse * vec4(eyeDir.xyz, 0.0));\n }\n\n \n // Position is supposed to come in clip space\n gl_Position = vec4(inPosition.xy, 0.0, 1.0);\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:38 2018\n// skybox.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform samplerCube cubeMap;\n\nstruct Skybox {\n vec4 color;\n};\n\nuniform skyboxBuffer {\n Skybox skybox;\n};\n\nlayout(location = 0) in vec3 _normal;\nlayout(location = 0) out vec4 _fragColor;\n\n//PROCEDURAL_COMMON_BLOCK\n\n#line 1001\n//PROCEDURAL_BLOCK\n\n#line 2033\nvoid main(void) {\n\n#ifdef PROCEDURAL\n\n vec3 color = getSkyboxColor();\n // Protect from NaNs and negative values\n color = mix(color, vec3(0), isnan(color));\n color = max(color, vec3(0));\n // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline\n color = pow(color, vec3(2.2));\n _fragColor = vec4(color, 0.0);\n\n // FIXME: scribe does not yet scrub out else statements\n return;\n\n#else \n vec3 coord = normalize(_normal);\n vec3 color = skybox.color.rgb;\n\n // blend is only set if there is a cubemap\n if (skybox.color.a > 0.0) {\n color = texture(cubeMap, coord).rgb;\n if (skybox.color.a < 1.0) {\n color *= skybox.color.rgb;\n }\n }\n _fragColor = vec4(color, 0.0);\n\n#endif\n\n}\n\n\n" }, - "YV/68ATVBHT8FBzosoAaOQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Tue May 22 11:51:57 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_textured_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb+fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb+fadeEmissive);\n }\n}\n\n", - "type": 36385 + "CMomjaLoGqMsZMDrr//xag==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "Yg27LgkS/kNE2IaqvUmG7g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "DbXVJSaflA+BRMZFQs25WA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// velocityBuffer_cameraMotion.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D depthMap;\n\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n \n\tfloat Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n\n\t// The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalUnjitteredEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);\n\tvec3 worldPos = (getViewInverse() * vec4(eyePos, 1.0)).xyz;\n \n vec3 prevEyePos = (getPreviousView() * vec4(worldPos, 1.0)).xyz;\n vec4 prevClipPos = (getUnjitteredProjection(stereoSide.x) * vec4(prevEyePos, 1.0));\n vec2 prevUV = 0.5 * (prevClipPos.xy / prevClipPos.w) + vec2(0.5);\n\n //vec2 imageSize = getWidthHeight(0);\n vec2 imageSize = vec2(1.0, 1.0);\n outFragColor = vec4( ((texcoordPos - prevUV) * imageSize), 0.0, 0.0);\n}\n\n\n" }, - "Ym52B0M7XXKrwtbSW3OxAQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_textured.slf\n// fragment shader\n//\n// Created by Clément Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n}\n\n", - "type": 36385 + "EG2IuGsgmBcJjNk/YAaKqw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent.vert\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "Z1tT4pxpQeQl4K/U/AOEVA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:49:40 2018\n// skybox.vert\n// vertex shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _normal;\n\nvoid main(void) {\n const float depth = 0.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 inPosition = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n vec3 clipDir = vec3(inPosition.xy, 0.0);\n vec3 eyeDir;\n { // transformClipToEyeDir\n eyeDir = vec3(cam._projectionInverse * vec4(clipDir.xyz, 1.0)); // Must be 1.0 here\n }\n\n { // transformEyeToWorldDir\n _normal = vec3(cam._viewInverse * vec4(eyeDir.xyz, 0.0));\n }\n\n \n // Position is supposed to come in clip space\n gl_Position = vec4(inPosition.xy, 0.0, 1.0);\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:49:40 2018\n// skybox.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform samplerCube cubeMap;\n\nstruct Skybox {\n vec4 color;\n};\n\nuniform skyboxBuffer {\n Skybox skybox;\n};\n\nin vec3 _normal;\nout vec4 _fragColor;\n\n//PROCEDURAL_COMMON_BLOCK\n\n#line 1001\n//PROCEDURAL_BLOCK\n\n#line 2033\nvoid main(void) {\n\n#ifdef PROCEDURAL\n\n vec3 color = getSkyboxColor();\n // Protect from NaNs and negative values\n color = mix(color, vec3(0), isnan(color));\n color = max(color, vec3(0));\n // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline\n color = pow(color, vec3(2.2));\n _fragColor = vec4(color, 0.0);\n\n // FIXME: scribe does not yet scrub out else statements\n return;\n\n#else \n vec3 coord = normalize(_normal);\n vec3 color = skybox.color.rgb;\n\n // blend is only set if there is a cubemap\n if (skybox.color.a > 0.0) {\n color = texture(cubeMap, coord).rgb;\n if (skybox.color.a < 1.0) {\n color *= skybox.color.rgb;\n }\n }\n _fragColor = vec4(color, 0.0);\n\n#endif\n\n}\n\n\n", - "type": 36385 + "FMMwR7cPDX2l4zmI4MipUA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// standardTransformPNTC.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTextureOpaque.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n// Alpha is 1\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(texture(colorMap, varTexCoord0).xyz, 1.0);\n}\n\n\n" }, - "ZJCzpkP3UAEJafTFMwS66g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "FWQxyxWPPa+OEK1hceNbvA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "ZYzUJv2/hQhTpeicrFb/Fg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:52:00 2018\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n\nuniform sampler2D depthMap;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n float Zeye = -evalZeyeFromZdb(Zdb);\n outFragColor = vec4(Zeye, 0.0, 0.0, 1.0);\n}\n\n\n\n", - "type": 36385 + "FnU12MybTZGltNrZuBl8aA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_makeLinearDepth.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n\nuniform sampler2D depthMap;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n float Zeye = -evalZeyeFromZdb(Zdb);\n outFragColor = vec4(Zeye, 0.0, 0.0, 1.0);\n}\n\n\n\n" }, - "b5FtiDU5bKxzuM+zfAKuEA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Tue May 22 11:51:57 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_transparent_textured_unlit_fade.slf\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor0;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb + fadeEmissive, colorAlpha * texel.a);\n}\n\n", - "type": 36385 + "FvDaaBFKlFq2M97g5NVmCA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n" }, - "e8lwdJtkDctZ7NEbyhyxwg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_fade.slv\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n\n\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "G2a+Y4aUEqhZn7hakpwZFQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// standardTransformPNTC.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// standardDrawTexture.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/10/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// the texture\nuniform sampler2D colorMap;\n\nin vec3 varPosition;\nin vec3 varNormal;\nin vec2 varTexCoord0;\nin vec4 varColor;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n vec4 color = texture(colorMap, varTexCoord0);\n outFragColor = color * varColor;\n}\n\n\n" }, - "eObKu0PvvOOyGAm/THhmbw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "G46XKIM0jJ6vgDbngE52hQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "f0TUiQbeEAqxpp8zuF8ZpA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model.slv\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// model_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/3/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n", - "type": 36385 + "GOAzIGB6zqkuFtzp9rtLOg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_makeLinearDepth.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n\nuniform sampler2D depthMap;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n float Zeye = -evalZeyeFromZdb(Zdb);\n outFragColor = vec4(Zeye, 0.0, 0.0, 1.0);\n}\n\n\n\n" }, - "f27bv1BfdhjolYPObUXJdw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// overlay3D.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// overlay3D.slf\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled();\n color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled();\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a;\n\n if (fragOpacity <= 0.1) {\n discard;\n }\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n", - "type": 36385 + "HFU9mHLJX5P5/IfniUnl8A==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "fY/fQ+FyIzzKi2TO5G1aeA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_lightmap_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_lightmap_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n", - "type": 36385 + "HRnAky0KbclLNFv8f2spcA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "ftgoXnXTs0Yz1w+VNg2NSA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\n\nvec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n\n vec2 finalStep = getFilterScale() * direction * pixelStep;\n vec4 srcBlurred = vec4(0.0);\n float totalWeight = 0.f;\n int numTaps = getFilterNumTaps();\n \n for(int i = 0; i < numTaps; i++) {\n vec2 tapInfo = getFilterTap(i);\n // Fetch color for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n }\n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n srcBlurred.a = getOutputAlpha();\n return srcBlurred;\n}\n\n\n\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussian(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n", - "type": 36385 + "Hg1/zhYJuA3PGnI8pJnDNA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "gDAXqBAQa5wJi1fT2KtrVg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// overlay3D.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// overlay3D_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n _fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha);\n}\n\n\n", - "type": 36385 + "I1NME6mcvVUMbl/SdAU7Og==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeLUT.frag\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\nvec3 integrate(float cosTheta, float skinRadius) {\n // Angle from lighting direction.\n float theta = acos(cosTheta);\n vec3 totalWeights = vec3(0.0);\n vec3 totalLight = vec3(0.0);\n\n const float _PI = 3.14159265358979523846;\n const float step = 2.0 * _PI / float(2000);\n float a = -(_PI);\n\n\n while (a <= (_PI)) {\n float sampleAngle = theta + a;\n float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);\n //if (diffuse < 0.0) diffuse = 0.0;\n //if (diffuse > 1.0) diffuse = 1.0;\n\n // Distance.\n float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5));\n\n // Profile Weight.\n vec3 weights = scatter(sampleDist);\n\n totalWeights += weights;\n totalLight += diffuse * weights;\n a += step;\n }\n\n vec3 result = (totalLight / totalWeights);\n return clamp(result, vec3(0.0), vec3(1.0));\n\n}\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n\n // Lookup by: x: NDotL y: 1 / r\n //float y = 2.0 * 1.0 / ((j + 1.0) / (double)height);\n //float x = ((i / (double)width) * 2.0) - 1.0;\n\n outFragColor = vec4(integrate(varTexCoord0.x * 2.0 - 1.0, 2.0 / varTexCoord0.y), 1.0);\n}\n\n\n\n" }, - "gl8LXKtp/tv2c/qyy/5e/g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nstruct SurfaceGeometryParams {\n // Resolution info\n vec4 resolutionInfo;\n // Curvature algorithm\n vec4 curvatureInfo;\n};\n\nuniform surfaceGeometryParamsBuffer {\n SurfaceGeometryParams params;\n};\n\nfloat getCurvatureDepthThreshold() {\n return params.curvatureInfo.x;\n}\n\nfloat getCurvatureBasisScale() {\n return params.curvatureInfo.y;\n}\n\nfloat getCurvatureScale() {\n return params.curvatureInfo.w;\n}\n\nbool isFullResolution() {\n return params.resolutionInfo.w == 0.0;\n}\n\n\nuniform sampler2D linearDepthMap;\nfloat getZEye(ivec2 pixel) {\n return -texelFetch(linearDepthMap, pixel, 0).x;\n}\nfloat getZEyeLinear(vec2 texcoord) {\n return -texture(linearDepthMap, texcoord).x;\n}\n\nvec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) {\n return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y);\n}\n\nuniform sampler2D normalMap;\n\nvec3 getRawNormal(vec2 texcoord) {\n return texture(normalMap, texcoord).xyz;\n}\n\nvec3 getWorldNormal(vec2 texcoord) {\n vec3 rawNormal = getRawNormal(texcoord);\n if (isFullResolution()) {\n return unpackNormal(rawNormal);\n } else {\n return normalize((rawNormal - vec3(0.5)) * 2.0);\n }\n}\n\nvec3 getWorldNormalDiff(vec2 texcoord, vec2 delta) {\n return getWorldNormal(texcoord + delta) - getWorldNormal(texcoord - delta);\n}\n\nfloat getEyeDepthDiff(vec2 texcoord, vec2 delta) {\n return getZEyeLinear(texcoord + delta) - getZEyeLinear(texcoord - delta);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n vec2 stereoSideClip = vec2(stereoSide.x, (isStereo() ? 0.5 : 1.0));\n\n // Texcoord to fetch in the deferred texture are the exact UVs comming from vertex shader\n // sideToFrameTexcoord(stereoSideClip, texcoordPos);\n vec2 frameTexcoordPos = varTexCoord0;\n\n // Fetch the z under the pixel (stereo or not)\n float Zeye = getZEye(framePixelPos);\n if (Zeye <= -getPosLinearDepthFar()) {\n outFragColor = vec4(1.0, 0.0, 0.0, 0.0);\n return;\n }\n\n float nearPlaneScale = 0.5 * getProjectionNear();\n\n vec3 worldNormal = getWorldNormal(frameTexcoordPos);\n\n // The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos);\n // vec3 worldPos = (frameTransform._viewInverse * vec4(eyePos, 1.0)).xyz;\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(10.0 * eyePos.xyz), 1.0);\n }*/\n // return;\n\n // Calculate the perspective scale.\n // Clamp to 0.5\n // float perspectiveScale = max(0.5, (-getProjScaleEye() / Zeye));\n float perspectiveScale = max(0.5, (-getCurvatureBasisScale() * getProjectionNear() / Zeye));\n\n // Calculate dF/du and dF/dv\n vec2 viewportScale = perspectiveScale * getInvWidthHeight();\n vec2 du = vec2( viewportScale.x * (float(stereoSide.w) > 0.0 ? 0.5 : 1.0), 0.0f );\n vec2 dv = vec2( 0.0f, viewportScale.y );\n\n vec4 dFdu = vec4(getWorldNormalDiff(frameTexcoordPos, du), getEyeDepthDiff(frameTexcoordPos, du));\n vec4 dFdv = vec4(getWorldNormalDiff(frameTexcoordPos, dv), getEyeDepthDiff(frameTexcoordPos, dv));\n\n float threshold = getCurvatureDepthThreshold();\n dFdu *= step(abs(dFdu.w), threshold);\n dFdv *= step(abs(dFdv.w), threshold); \n\n // Calculate ( du/dx, du/dy, du/dz ) and ( dv/dx, dv/dy, dv/dz )\n // Eval px, py, pz world positions of the basis centered on the world pos of the fragment\n float axeLength = nearPlaneScale;\n\n vec3 ax = (frameTransform._view[0].xyz * axeLength);\n vec3 ay = (frameTransform._view[1].xyz * axeLength);\n vec3 az = (frameTransform._view[2].xyz * axeLength);\n\n\n\n vec4 px = vec4(eyePos + ax, 0.0);\n vec4 py = vec4(eyePos + ay, 0.0);\n vec4 pz = vec4(eyePos + az, 0.0);\n\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(px.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(eyePos.xyz), 1.0);\n }*/\n // return;\n\n\n /* IN case the axis end point goes behind mid way near plane, this shouldn't happen\n if (px.z >= -nearPlaneScale) {\n outFragColor = vec4(1.0, 0.0, 0.0, 1.0);\n return;\n } else if (py.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 1.0, 0.0, 1.0);\n return;\n } else if (pz.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 0.0, 1.0, 1.0);\n return;\n }*/\n \n\n // Project px, py pz to homogeneous clip space\n // mat4 viewProj = getProjection(stereoSide.x);\n mat4 viewProj = getProjectionMono();\n px = viewProj * px;\n py = viewProj * py;\n pz = viewProj * pz;\n\n\n // then to normalized clip space\n px.xy /= px.w;\n py.xy /= py.w;\n pz.xy /= pz.w;\n\n vec2 nclipPos = (texcoordPos - 0.5) * 2.0;\n\n\n //vec4 clipPos = frameTransform._projection[stereoSide.x] * vec4(eyePos, 1.0);\n vec4 clipPos = getProjectionMono() * vec4(eyePos, 1.0);\n nclipPos = clipPos.xy / clipPos.w;\n\n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (nclipPos)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (clipPos.xy / clipPos.w)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n //return;\n\n\n float pixPerspectiveScaleInv = 1.0 / (perspectiveScale);\n px.xy = (px.xy - nclipPos) * pixPerspectiveScaleInv;\n py.xy = (py.xy - nclipPos) * pixPerspectiveScaleInv;\n pz.xy = (pz.xy - nclipPos) * pixPerspectiveScaleInv;\n \n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (px.xy)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (py.xy)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n // return;\n\n // Calculate dF/dx, dF/dy and dF/dz using chain rule\n vec4 dFdx = dFdu * px.x + dFdv * px.y;\n vec4 dFdy = dFdu * py.x + dFdv * py.y;\n vec4 dFdz = dFdu * pz.x + dFdv * pz.y;\n\n vec3 trace = vec3(dFdx.x, dFdy.y, dFdz.z);\n\n /*if (dot(trace, trace) > params.curvatureInfo.w) {\n outFragColor = vec4(dFdx.x, dFdy.y, dFdz.z, 1.0);\n return;\n }*/\n\n // Calculate the mean curvature\n float meanCurvature = ((trace.x + trace.y + trace.z) * 0.33333333333333333) * params.curvatureInfo.w;\n\n outFragColor = vec4(vec3(worldNormal + 1.0) * 0.5, (meanCurvature + 1.0) * 0.5);\n}\n\n\n", - "type": 36385 + "IJ62ZMCaEEKluYEcsDAtrQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// taa.frag\n// fragment shader\n//\n// Created by Sam Gateau on 8/14/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// TAA.slh\n// Common component needed by TemporalAntialiasing fragment shader\n//\n// Created by Sam Gateau on 8/17/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nuniform sampler2D depthMap;\nuniform sampler2D sourceMap;\nuniform sampler2D historyMap;\nuniform sampler2D velocityMap;\nuniform sampler2D nextMap;\n\nstruct TAAParams\n{\n\tfloat none;\n\tfloat blend;\n\tfloat covarianceGamma;\n\tfloat debugShowVelocityThreshold;\n ivec4 flags;\n vec4 pixelInfo_orbZoom;\n vec4 regionInfo;\n};\n\nlayout(std140) uniform taaParamsBuffer {\n TAAParams params;\n};\n\n#define GET_BIT(bitfield, bitIndex) bool((bitfield) & (1 << (bitIndex)))\n\nbool taa_isDebugEnabled() {\n return GET_BIT(params.flags.x, 0);\n}\n\nbool taa_showDebugCursor() {\n return GET_BIT(params.flags.x, 1);\n}\n\nbool taa_showClosestFragment() {\n return GET_BIT(params.flags.x, 3);\n}\n\nbool taa_constrainColor() {\n return GET_BIT(params.flags.y, 1);\n}\n\nbool taa_feedbackColor() {\n return GET_BIT(params.flags.y, 4);\n}\n\nvec2 taa_getDebugCursorTexcoord() {\n return params.pixelInfo_orbZoom.xy;\n}\n\nfloat taa_getDebugOrbZoom() {\n return params.pixelInfo_orbZoom.z;\n}\n\nvec2 taa_getRegionDebug() {\n return params.regionInfo.xy;\n}\n\nvec2 taa_getRegionFXAA() {\n return params.regionInfo.zw;\n}\n#define USE_YCOCG 1\n\nvec4 taa_fetchColor(sampler2D map, vec2 uv) {\n\tvec4 c = texture(map, uv);\n\t// Apply rapid pseudo tonemapping as TAA is applied to a tonemapped image, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),c.rgb);\n\tc.rgb = c.rgb / (1.0+lum);\n#if USE_YCOCG\n\treturn vec4(color_LinearToYCoCg(c.rgb), c.a);\n#else\n\treturn c;\n#endif\n}\n\nvec3 taa_resolveColor(vec3 color) {\n#if USE_YCOCG\n\tcolor = max(vec3(0), color_YCoCgToUnclampedLinear(color));\n#endif\n\t// Apply rapid inverse tonemapping, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),color.rgb);\n\tcolor = color / (1.0-lum);\n\treturn color;\n}\n\nvec4 taa_fetchSourceMap(vec2 uv) {\n\treturn taa_fetchColor(sourceMap, uv);\n}\n\nvec4 taa_fetchHistoryMap(vec2 uv) {\n\treturn taa_fetchColor(historyMap, uv);\n}\n\nvec4 taa_fetchNextMap(vec2 uv) {\n\treturn taa_fetchColor(nextMap, uv);\n}\n\nvec2 taa_fetchVelocityMap(vec2 uv) {\n\treturn texture(velocityMap, uv).xy;\n}\n\nfloat taa_fetchDepth(vec2 uv) {\n\treturn -texture(depthMap, vec2(uv), 0).x;\n}\n\n\n#define ZCMP_GT(a, b) (a > b)\n\nvec2 taa_getImageSize() {\n vec2 imageSize = getWidthHeight(0);\n if (isStereo()) {\n imageSize.x *= 2.0;\n }\n return imageSize;\n}\n\nvec2 taa_getTexelSize() {\n vec2 texelSize = getInvWidthHeight();\n if (isStereo()) {\n texelSize.x *= 0.5;\n }\n return texelSize;\n}\n\nvec3 taa_findClosestFragment3x3(vec2 uv)\n{\n\tvec2 dd = abs(taa_getTexelSize());\n\tvec2 du = vec2(dd.x, 0.0);\n\tvec2 dv = vec2(0.0, dd.y);\n\n\tvec3 dtl = vec3(-1, -1, taa_fetchDepth(uv - dv - du));\n\tvec3 dtc = vec3( 0, -1, taa_fetchDepth(uv - dv));\n\tvec3 dtr = vec3( 1, -1, taa_fetchDepth(uv - dv + du));\n\n\tvec3 dml = vec3(-1, 0, taa_fetchDepth(uv - du));\n\tvec3 dmc = vec3( 0, 0, taa_fetchDepth(uv));\n\tvec3 dmr = vec3( 1, 0, taa_fetchDepth(uv + du));\n\n\tvec3 dbl = vec3(-1, 1, taa_fetchDepth(uv + dv - du));\n\tvec3 dbc = vec3( 0, 1, taa_fetchDepth(uv + dv));\n\tvec3 dbr = vec3( 1, 1, taa_fetchDepth(uv + dv + du));\n\n\tvec3 dmin = dtl;\n\tif (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc;\n\tif (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr;\n\n\tif (ZCMP_GT(dmin.z, dml.z)) dmin = dml;\n\tif (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc;\n\tif (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr;\n\n\tif (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl;\n\tif (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc;\n\n\n\tif (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr;\n\n\treturn vec3(uv + dd.xy * dmin.xy, dmin.z);\n}\n\nvec2 taa_fetchVelocityMapBest(vec2 uv) {\n vec2 dd = abs(taa_getTexelSize());\n vec2 du = vec2(dd.x, 0.0);\n vec2 dv = vec2(0.0, dd.y);\n\n vec2 dtl = taa_fetchVelocityMap(uv - dv - du);\n vec2 dtc = taa_fetchVelocityMap(uv - dv);\n vec2 dtr = taa_fetchVelocityMap(uv - dv + du);\n\n vec2 dml = taa_fetchVelocityMap(uv - du);\n vec2 dmc = taa_fetchVelocityMap(uv);\n vec2 dmr = taa_fetchVelocityMap(uv + du);\n\n vec2 dbl = taa_fetchVelocityMap(uv + dv - du);\n vec2 dbc = taa_fetchVelocityMap(uv + dv);\n vec2 dbr = taa_fetchVelocityMap(uv + dv + du);\n\n vec3 best = vec3(dtl, dot(dtl,dtl));\n\n float testSpeed = dot(dtc,dtc);\n if (testSpeed > best.z) { best = vec3(dtc, testSpeed); }\n testSpeed = dot(dtr,dtr);\n if (testSpeed > best.z) { best = vec3(dtr, testSpeed); }\n\n testSpeed = dot(dml,dml);\n if (testSpeed > best.z) { best = vec3(dml, testSpeed); }\n testSpeed = dot(dmc,dmc);\n if (testSpeed > best.z) { best = vec3(dmc, testSpeed); }\n testSpeed = dot(dmr,dmr);\n if (testSpeed > best.z) { best = vec3(dmr, testSpeed); }\n\n testSpeed = dot(dbl,dbl);\n if (testSpeed > best.z) { best = vec3(dbl, testSpeed); }\n testSpeed = dot(dbc,dbc);\n if (testSpeed > best.z) { best = vec3(dbc, testSpeed); }\n testSpeed = dot(dbr,dbr);\n if (testSpeed > best.z) { best = vec3(dbr, testSpeed); }\n\n return best.xy;\n}\n\nvec2 taa_fromFragUVToEyeUVAndSide(vec2 fragUV, out int stereoSide) {\n vec2 eyeUV = fragUV;\n stereoSide = 0;\n if (isStereo()) {\n if (eyeUV.x > 0.5) {\n eyeUV.x -= 0.5;\n stereoSide = 1;\n }\n eyeUV.x *= 2.0;\n }\n return eyeUV;\n}\n\nvec2 taa_fromEyeUVToFragUV(vec2 eyeUV, int stereoSide) {\n vec2 fragUV = eyeUV;\n if (isStereo()) {\n fragUV.x *= 0.5;\n fragUV.x += stereoSide*0.5;\n }\n return fragUV;\n}\n\nvec2 taa_computePrevFragAndEyeUV(vec2 fragUV, vec2 fragVelocity, out vec2 prevEyeUV) {\n int stereoSide = 0;\n vec2 eyeUV = taa_fromFragUVToEyeUVAndSide(fragUV, stereoSide);\n prevEyeUV = eyeUV - fragVelocity;\n return taa_fromEyeUVToFragUV(prevEyeUV, stereoSide);\n}\n\nvec2 taa_fetchSourceAndHistory(vec2 fragUV, vec2 fragVelocity, out vec3 sourceColor, out vec3 historyColor) {\n vec2 prevEyeUV;\n vec2 prevFragUV = taa_computePrevFragAndEyeUV(fragUV, fragVelocity, prevEyeUV);\n sourceColor = taa_fetchSourceMap(fragUV).xyz;\n\n historyColor = sourceColor;\n if (!(any(lessThan(prevEyeUV, vec2(0.0))) || any(greaterThan(prevEyeUV, vec2(1.0))))) {\n historyColor = taa_fetchHistoryMap(prevFragUV).xyz;\n }\n return prevFragUV;\n}\n\nfloat Luminance(vec3 rgb) {\n return rgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0;\n}\n\n#define MINMAX_3X3_ROUNDED 1\n\nmat3 taa_evalNeighbourColorVariance(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity) {\n vec2 texelSize = taa_getTexelSize();\n \n\n\tvec2 du = vec2(texelSize.x, 0.0);\n\tvec2 dv = vec2(0.0, texelSize.y);\n\n vec3 sampleColor = taa_fetchSourceMap(fragUV - dv - du).rgb;\n vec3 sumSamples = sampleColor;\n vec3 sumSamples2 = sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sampleColor isn't it ?\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n \n sampleColor = taa_fetchSourceMap(fragUV + dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n \n vec3 mu = sumSamples / vec3(9.0);\n vec3 sigma = sqrt(max(sumSamples2 / vec3(9.0) - mu * mu, vec3(0.0)));\n \n float gamma = params.covarianceGamma;\n vec3 cmin = mu - gamma * sigma;\n vec3 cmax = mu + gamma * sigma;\n\n return mat3(cmin, cmax, mu);\n}\n\nmat3 taa_evalNeighbourColorRegion(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity, float fragZe) {\n vec2 imageSize = taa_getImageSize();\n vec2 texelSize = taa_getTexelSize();\n vec3 cmin, cmax, cavg;\n\n #if MINMAX_3X3_ROUNDED\n\t\tvec2 du = vec2(texelSize.x, 0.0);\n\t\tvec2 dv = vec2(0.0, texelSize.y);\n\n\t\tvec3 ctl = taa_fetchSourceMap(fragUV - dv - du).rgb;\n\t\tvec3 ctc = taa_fetchSourceMap(fragUV - dv).rgb;\n\t\tvec3 ctr = taa_fetchSourceMap(fragUV - dv + du).rgb;\n\t\tvec3 cml = taa_fetchSourceMap(fragUV - du).rgb;\n\t\tvec3 cmc = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sample isn't it ?\n\t\tvec3 cmr = taa_fetchSourceMap(fragUV + du).rgb;\n\t\tvec3 cbl = taa_fetchSourceMap(fragUV + dv - du).rgb;\n\t\tvec3 cbc = taa_fetchSourceMap(fragUV + dv).rgb;\n\t\tvec3 cbr = taa_fetchSourceMap(fragUV + dv + du).rgb;\n\n\t\tcmin = min(ctl, min(ctc, min(ctr, min(cml, min(cmc, min(cmr, min(cbl, min(cbc, cbr))))))));\n\t\tcmax = max(ctl, max(ctc, max(ctr, max(cml, max(cmc, max(cmr, max(cbl, max(cbc, cbr))))))));\n\n\t\t#if MINMAX_3X3_ROUNDED || USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (ctl + ctc + ctr + cml + cmc + cmr + cbl + cbc + cbr) / 9.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n\n\t\t#if MINMAX_3X3_ROUNDED\n\t\t\tvec3 cmin5 = min(ctc, min(cml, min(cmc, min(cmr, cbc))));\n\t\t\tvec3 cmax5 = max(ctc, max(cml, max(cmc, max(cmr, cbc))));\n\t\t\tvec3 cavg5 = (ctc + cml + cmc + cmr + cbc) / 5.0;\n\t\t\tcmin = 0.5 * (cmin + cmin5);\n\t\t\tcmax = 0.5 * (cmax + cmax5);\n\t\t\tcavg = 0.5 * (cavg + cavg5);\n\t\t#endif\n #else\n\t\tconst float _SubpixelThreshold = 0.5;\n\t\tconst float _GatherBase = 0.5;\n\t\tconst float _GatherSubpixelMotion = 0.1666;\n\n\t\tvec2 texel_vel = fragVelocity * imageSize;\n\t\tfloat texel_vel_mag = length(texel_vel) * -fragZe;\n\t\tfloat k_subpixel_motion = clamp(_SubpixelThreshold / (0.0001 + texel_vel_mag), 0.0, 1.0);\n\t\tfloat k_min_max_support = _GatherBase + _GatherSubpixelMotion * k_subpixel_motion;\n\n\t\tvec2 ss_offset01 = k_min_max_support * vec2(-texelSize.x, texelSize.y);\n\t\tvec2 ss_offset11 = k_min_max_support * vec2(texelSize.x, texelSize.y);\n\t\tvec3 c00 = taa_fetchSourceMap(fragUV - ss_offset11).rgb;\n\t\tvec3 c10 = taa_fetchSourceMap(fragUV - ss_offset01).rgb;\n\t\tvec3 c01 = taa_fetchSourceMap(fragUV + ss_offset01).rgb;\n\t\tvec3 c11 = taa_fetchSourceMap(fragUV + ss_offset11).rgb;\n\n\t\tcmin = min(c00, min(c10, min(c01, c11)));\n\t\tcmax = max(c00, max(c10, max(c01, c11)));\n cavg = (cmin + cmax ) * 0.5;\n\n\t\t#if USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (c00 + c10 + c01 + c11) / 4.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n #endif\n\n \t\t// shrink chroma min-max\n\t#if USE_YCOCG\n\t\tvec2 chroma_extent = vec2(0.25 * 0.5 * (cmax.r - cmin.r));\n\t\tvec2 chroma_center = sourceColor.gb;\n\t\tcmin.yz = chroma_center - chroma_extent;\n\t\tcmax.yz = chroma_center + chroma_extent;\n\t\tcavg.yz = chroma_center;\n\t#endif\n\n return mat3(cmin, cmax, cavg);\n}\n\n//#define USE_OPTIMIZATIONS 0\n\nvec3 taa_clampColor(vec3 colorMin, vec3 colorMax, vec3 colorSource, vec3 color) {\n\tconst float eps = 0.00001;\n vec3 p = colorSource;\n vec3 q = color;\n\t// note: only clips towards aabb center (but fast!)\n\tvec3 p_clip = 0.5 * (colorMax + colorMin);\n\tvec3 e_clip = 0.5 * (colorMax - colorMin) + vec3(eps);\n\n\tvec3 v_clip = q - p_clip;\n\tvec3 v_unit = v_clip.xyz / e_clip;\n\tvec3 a_unit = abs(v_unit);\n\tfloat ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z));\n\n\tif (ma_unit > 1.0)\n\t\treturn p_clip + v_clip / ma_unit;\n\telse\n\t\treturn q;// point inside aabb\t\t\n}\n\nvec3 taa_evalConstrainColor(vec3 sourceColor, vec2 sourceUV, vec2 sourceVel, vec3 candidateColor) {\n mat3 colorMinMaxAvg;\n\n colorMinMaxAvg = taa_evalNeighbourColorVariance(sourceColor, sourceUV, sourceVel);\n \n\t// clamp history to neighbourhood of current sample\n return taa_clampColor(colorMinMaxAvg[0], colorMinMaxAvg[1], sourceColor, candidateColor);\n}\n\nvec3 taa_evalFeedbackColor(vec3 sourceColor, vec3 historyColor, float blendFactor) {\n const float _FeedbackMin = 0.1;\n const float _FeedbackMax = 0.9;\n\t// feedback weight from unbiased luminance diff (t.lottes)\n\t#if USE_YCOCG\n\t\tfloat lum0 = sourceColor.r;\n\t\tfloat lum1 = historyColor.r;\n\t#else\n\t\tfloat lum0 = Luminance(sourceColor.rgb);\n\t\tfloat lum1 = Luminance(historyColor.rgb);\n\t#endif\n\tfloat unbiased_diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));\n\tfloat unbiased_weight = 1.0 - unbiased_diff;\n\tfloat unbiased_weight_sqr = unbiased_weight * unbiased_weight;\n\tfloat k_feedback = mix(_FeedbackMin, _FeedbackMax, unbiased_weight_sqr);\n\n \n vec3 nextColor = mix(historyColor, sourceColor, k_feedback * blendFactor).xyz;\n return nextColor;\n}\n\n\nvec3 colorWheel(float normalizedHue) {\n float v = normalizedHue * 6.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n } else if (v < 2.f) {\n return vec3(1.f - (v-1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v-2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v-3.f), 1.f );\n } else if (v < 5.f) {\n return vec3((v-4.f), 0.f, 1.f );\n } else if (v < 6.f) {\n return vec3(1.f, 0.f, 1.f - (v-5.f));\n } else {\n return vec3(1.f, 0.f, 0.f);\n }\n}\n\nvec3 colorRamp(float normalizedHue) {\n float v = normalizedHue * 5.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n\n\n } else if (v < 2.f) {\n return vec3(1.f - (v - 1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v - 2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v - 3.f), 1.f);\n } else if (v < 5.f) {\n return vec3((v - 4.f), 0.f, 1.f);\n } else {\n return vec3(1.f, 0.f, 1.f);\n }\n}\n\n\nvec3 taa_getVelocityColorRelative(float velocityPixLength) {\n return colorRamp(velocityPixLength/params.debugShowVelocityThreshold);\n}\n\nvec3 taa_getVelocityColorAboveThreshold(float velocityPixLength) {\n return colorRamp((velocityPixLength - params.debugShowVelocityThreshold)/params.debugShowVelocityThreshold);\n}\n\n\nvec3 taa_evalFXAA(vec2 fragUV) {\n\n // vec2 texelSize = getInvWidthHeight();\n vec2 texelSize = taa_getTexelSize();\n\n // filter width limit for dependent \"two-tap\" texture samples\n float FXAA_SPAN_MAX = 8.0;\n\n // local contrast multiplier for performing AA\n // higher = sharper, but setting this value too high will cause near-vertical and near-horizontal edges to fail\n // see \"fxaaQualityEdgeThreshold\"\n float FXAA_REDUCE_MUL = 1.0 / 8.0;\n\n // luminance threshold for processing dark colors\n // see \"fxaaQualityEdgeThresholdMin\"\n float FXAA_REDUCE_MIN = 1.0 / 128.0;\n\n // fetch raw RGB values for nearby locations\n // sampling pattern is \"five on a die\" (each diagonal direction and the center)\n // computing the coordinates for these texture reads could be moved to the vertex shader for speed if needed\n vec3 rgbNW = texture(sourceMap, fragUV + (vec2(-1.0, -1.0) * texelSize)).xyz;\n vec3 rgbNE = texture(sourceMap, fragUV + (vec2(+1.0, -1.0) * texelSize)).xyz;\n vec3 rgbSW = texture(sourceMap, fragUV + (vec2(-1.0, +1.0) * texelSize)).xyz;\n vec3 rgbSE = texture(sourceMap, fragUV + (vec2(+1.0, +1.0) * texelSize)).xyz;\n vec3 rgbM = texture(sourceMap, fragUV).xyz;\n\t\n // convert RGB values to luminance\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot( rgbM, luma);\n\t\n // luma range of local neighborhood\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\t\n // direction perpendicular to local luma gradient\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n // compute clamped direction offset for additional \"two-tap\" samples\n // longer vector = blurry, shorter vector = sharp\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), \n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize;\n\t\t\n // perform additional texture sampling perpendicular to gradient\n vec3 rgbA = (1.0 / 2.0) * (\n texture(sourceMap, fragUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (\n texture(sourceMap, fragUV + dir * (0.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (3.0 / 3.0 - 0.5)).xyz);\n float lumaB = dot(rgbB, luma);\n\n // compare luma of new samples to the luma range of the original neighborhood\n // if the new samples exceed this range, just use the first two samples instead of all four\n if (lumaB < lumaMin || lumaB > lumaMax) {\n return rgbA;\n } else {\n return rgbB;\n }\n}in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main() {\n vec2 fragUV = varTexCoord0;\n\n // Debug region before debug or fxaa region X\n float distToRegionFXAA = fragUV.x - taa_getRegionFXAA().x; \n if (distToRegionFXAA > 0.0) {\n outFragColor = vec4(taa_evalFXAA(fragUV), 1.0);\n return;\n }\n\n vec2 fragVel = taa_fetchVelocityMapBest(fragUV).xy;\n\n vec3 sourceColor;\n vec3 historyColor;\n vec2 prevFragUV = taa_fetchSourceAndHistory(fragUV, fragVel, sourceColor, historyColor);\n\n vec3 nextColor = sourceColor;\n \n if (taa_constrainColor()) {\n // clamp history to neighbourhood of current sample\n historyColor = taa_evalConstrainColor(sourceColor, fragUV, fragVel, historyColor);\n }\n \n if (taa_feedbackColor()) {\n nextColor = taa_evalFeedbackColor(sourceColor, historyColor, params.blend);\n } else {\n nextColor = mix(historyColor, sourceColor, params.blend);\n }\n\n outFragColor = vec4(taa_resolveColor(nextColor), 1.0);\n}\n\n\n" }, - "gs0v2SCaNxSn4xjjbkD7/g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 16 13:24:57 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(0.0, 1.0), getViewportInvWidthHeight());\n}\n\n\n\n", - "type": 36385 + "IYnWu6i5FAKpknqGF8kWag==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// Haze.frag\n//\n// Created by Nissim Hadar on 9/5/2107.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n\n\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n\n\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n\n\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nuniform sampler2D colorMap;\nuniform sampler2D linearDepthMap;\n\nvec4 unpackPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearDepthMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n if ((isHazeEnabled() == 0.0) || (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) {\n discard;\n }\n\n vec4 fragColor = texture(colorMap, varTexCoord0);\n vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);\n\n mat4 viewInverse = getViewInverse();\n vec4 fragPositionWS = viewInverse * fragPositionES;\n vec4 eyePositionWS = viewInverse[3];\n\n Light light = getKeyLight();\n vec3 lightDirectionWS = getLightDirection(light);\n\n outFragColor = computeHazeColor(fragColor, fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);\n}\n\n\n" }, - "hZdxM0lGXUjO1wO4D7hpOQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_translucent_normal_map.slv\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n\n\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "J0EApsSNXA43OTVFxWYe2w==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "jgm72cnfaUKJB9D5Gvtp4Q==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_lightmap.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_lightmap_specular_map.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n", - "type": 36385 + "JefB90FYCNd4kFnBpAxuYw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "km56v5kRTwhQeUs/WgMCtQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n\n\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "JrU2NNcLi2CpWUGd110RBQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "lTthzzu3fDr6TLpOfD1prQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// forward_simple_textured_transparent.slf\n// fragment shader\n//\n// Created by Clément Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n\n\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n\n\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n\n\n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n // FIXME - temporarily removed until we support it for forward...\n /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }*/\n\n return color;\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionES;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n TransformCamera cam = getTransformCamera();\n vec3 fragPosition = _positionES.xyz;\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n DEFAULT_OCCLUSION,\n fragPosition,\n normalize(_normalWS),\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_ROUGHNESS, colorAlpha),\n colorAlpha);\n}\n\n", - "type": 36385 + "JztsCp1r0zhCcplOJSKEIg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianDepthAwareH.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n" }, - "lle5L4fzCwjLPg9bSlxn3A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// directional_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//!>\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\n\n\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nin vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n", - "type": 36385 + "KH6a9o7N1OosoXyKLBEv4w==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeSpecularBeckmann.frag\n//\n// Created by Sam Gateau on 6/30/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nfloat specularBeckmann(float ndoth, float roughness) {\n float alpha = acos(ndoth);\n float ta = tan(alpha);\n float val = 1.0 / (roughness * roughness * pow(ndoth, 4.0)) * exp(-(ta * ta) / (roughness * roughness));\n return val;\n}\n\nvoid main(void) {\n outFragColor = vec4(vec3(0.5 * pow( specularBeckmann(varTexCoord0.x, varTexCoord0.y), 0.1)), 1.0);\n}\n\n\n" }, - "lyp6fxQNrMiX641NvxBbxQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// sdf_text3D.vert\n// vertex shader\n//\n// Created by Brad Davis on 10/14/13.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec2 _texCoord0;\n\nvoid main() {\n _texCoord0 = inTexCoord0.xy;\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n const vec3 normal = vec3(0, 0, 1);\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, normal), dot(mr1, normal), dot(mr2, normal));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n// sdf_text3D_transparent.frag\n// fragment shader\n//\n// Created by Bradley Austin Davis on 2015-02-04\n// Based on fragment shader code from \n// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp \n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n\n\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\nuniform sampler2D Font;\nuniform bool Outline;\nuniform vec4 Color;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec2 _texCoord0;\n\nconst float gamma = 2.2;\nconst float smoothing = 32.0;\nconst float interiorCutoff = 0.8;\nconst float outlineExpansion = 0.2;\n\nvoid main() {\n // retrieve signed distance\n float sdf = texture(Font, _texCoord0).g;\n if (Outline) {\n if (sdf > interiorCutoff) {\n sdf = 1.0 - sdf;\n } else {\n sdf += outlineExpansion;\n }\n }\n // perform adaptive anti-aliasing of the edges\n // The larger we're rendering, the less anti-aliasing we need\n\n\n float s = smoothing * length(fwidth(_texCoord0));\n float w = clamp(s, 0.0, 0.5);\n float a = smoothstep(0.5 - w, 0.5 + w, sdf);\n \n // discard if invisible\n if (a < 0.01) {\n discard;\n }\n\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n a * Color.a,\n Color.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n}\n\n", - "type": 36385 + "KZyjNGIHl9JvqHP/edr1yg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" }, - "mlTHr+tXXkj/h8tqUvLvtA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Sat Oct 24 09:34:37 2015\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct ToneMappingParams {\n vec4 _exp_2powExp_s0_s1;\n ivec4 _toneCurve_s0_s1_s2;\n};\n\nconst float INV_GAMMA_22 = 1.0 / 2.2;\nconst int ToneCurveNone = 0;\nconst int ToneCurveGamma22 = 1;\nconst int ToneCurveReinhard = 2;\nconst int ToneCurveFilmic = 3;\n\nuniform toneMappingParamsBuffer {\n ToneMappingParams params;\n};\nfloat getTwoPowExposure() {\n return params._exp_2powExp_s0_s1.y;\n}\nint getToneCurve() {\n return params._toneCurve_s0_s1_s2.x;\n}\n\nuniform sampler2D colorMap;\n \nin vec2 varTexCoord0;\nout vec4 outFragColor;\n \nvoid main(void) {\n vec4 fragColorRaw = texture(colorMap, varTexCoord0);\n vec3 fragColor = fragColorRaw.xyz;\n\n vec3 srcColor = fragColor * getTwoPowExposure();\n\n int toneCurve = getToneCurve();\n vec3 tonedColor = srcColor;\n if (toneCurve == ToneCurveFilmic) {\n vec3 x = max(vec3(0.0), srcColor-0.004);\n tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);\n } else if (toneCurve == ToneCurveReinhard) {\n tonedColor = srcColor/(1.0 + srcColor);\n tonedColor = pow(tonedColor, vec3(INV_GAMMA_22));\n } else if (toneCurve == ToneCurveGamma22) {\n tonedColor = pow(srcColor, vec3(INV_GAMMA_22));\n } // else None toned = src\n\n outFragColor = vec4(tonedColor, 1.0);\n}\n\n\n", - "type": 36385 + "KwPjt0+3ZrXGpMVUhBkSTg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianH.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\n\nvec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n\n vec2 finalStep = getFilterScale() * direction * pixelStep;\n vec4 srcBlurred = vec4(0.0);\n float totalWeight = 0.f;\n int numTaps = getFilterNumTaps();\n \n for(int i = 0; i < numTaps; i++) {\n vec2 tapInfo = getFilterTap(i);\n // Fetch color for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n }\n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n srcBlurred.a = getOutputAlpha();\n return srcBlurred;\n}\n\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussian(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n" }, - "mw8ZWaJjoCN5OFC7Va/07g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) out vec4 _fragColor;\n\nin vec4 _positionWS;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n", - "type": 36385 + "LZ9IXPsvRoIc6I+O+aAfXg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "n3QqD5tG9geQtyjUMWSK/Q==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_translucent_normal_map.slv\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "LckWrI5952bz7t4vrKO//w==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\nlayout(location = 5) in vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n" }, - "ny3BMXel0AI8dvh4z3Kkkg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Tue May 22 11:51:57 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_textured_fade.slf\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb + fadeEmissive,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragment(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb,\n DEFAULT_ROUGHNESS,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE + fadeEmissive,\n DEFAULT_OCCLUSION,\n DEFAULT_SCATTERING);\n }\n}\n\n", - "type": 36385 + "LdUCA2vslLE/h50ip4PzRA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// forward_simple_textured_transparent.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n\n\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n\n\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n\n\n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n // FIXME - temporarily removed until we support it for forward...\n /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }*/\n\n return color;\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nlayout(location = 0) in vec3 _normalWS;\nlayout(location = 1) in vec4 _color;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec4 _positionES;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n TransformCamera cam = getTransformCamera();\n vec3 fragPosition = _positionES.xyz;\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n DEFAULT_OCCLUSION,\n fragPosition,\n normalize(_normalWS),\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_METALLIC,\n DEFAULT_EMISSIVE,\n DEFAULT_ROUGHNESS, colorAlpha),\n colorAlpha);\n}\n\n" }, - "oON9LgrILcAUjRGvxiZ4fQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "M2eUZ1xdf1L900MdggmDRg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_unlit.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb);\n }\n}\n\n" }, - "pQ9n4mwkEq3N/g5kHnhw3g==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_fade.slv\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// model_translucent_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n\n\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n", - "type": 36385 + "Mw8Z4HCjs1MrjPNC9w6kUQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTexture.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n" }, - "seTEQye7AX4ZTuNv3Hrjvg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n\n\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "Ns2pr7qGfnAWa/Z2I70M1A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeLUT.frag\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\nvec3 integrate(float cosTheta, float skinRadius) {\n // Angle from lighting direction.\n float theta = acos(cosTheta);\n vec3 totalWeights = vec3(0.0);\n vec3 totalLight = vec3(0.0);\n\n const float _PI = 3.14159265358979523846;\n const float step = 2.0 * _PI / float(2000);\n float a = -(_PI);\n\n\n while (a <= (_PI)) {\n float sampleAngle = theta + a;\n float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);\n //if (diffuse < 0.0) diffuse = 0.0;\n //if (diffuse > 1.0) diffuse = 1.0;\n\n // Distance.\n float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5));\n\n // Profile Weight.\n vec3 weights = scatter(sampleDist);\n\n totalWeights += weights;\n totalLight += diffuse * weights;\n a += step;\n }\n\n vec3 result = (totalLight / totalWeights);\n return clamp(result, vec3(0.0), vec3(1.0));\n\n}\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n\n // Lookup by: x: NDotL y: 1 / r\n //float y = 2.0 * 1.0 / ((j + 1.0) / (double)height);\n //float x = ((i / (double)width) * 2.0) - 1.0;\n\n outFragColor = vec4(integrate(varTexCoord0.x * 2.0 - 1.0, 2.0 / varTexCoord0.y), 1.0);\n}\n\n\n\n" }, - "syfoNqvx3Kuur7/+HbkNbA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nout vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// local_lights_shading.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n\n\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n\n\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n\n\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}in vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n _fragColor = vec4(0.0);\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n\n\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord);\n vec4 fragPosition = frag.position;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragWorldPos = invViewMat * fragPosition;\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);\n }\n\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir);\n\n _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface, \n frag.metallic, frag.fresnel, frag.albedo, frag.scattering, \n midNormalCurvature, lowNormalCurvature, 1.0);\n\n}\n\n\n\n", - "type": 36385 + "NxqGRz3opuTH2bY3EmjfOA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n if (albedo.a <= 0.1) {\n discard;\n }\n vec4 color = vec4(albedo.rgb * _color, albedo.a);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" }, - "szTX4FocOWL7irfaWz6s6w==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Mon May 21 13:50:27 2018\n//\n// Draw texture 0 fetched at (1.0 - texcoord.x, texcoord.y)\n//\n// Created by Sam Gondelman on 10/24/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));\n}\n\n\n", - "type": 36385 + "O0nFCglOBDxnQ6h8RZJ0iw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled();\n color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled();\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a;\n\n if (fragOpacity <= 0.1) {\n discard;\n }\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" }, - "ufu+a6tNFhhCQIdBO9coeQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// overlay3D.slv\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// overlay3D_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n if (albedo.a <= 0.1) {\n discard;\n }\n vec4 color = vec4(albedo.rgb * _color, albedo.a);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n", - "type": 36385 + "OBUMls6ehY6dnh+ktMF4Rw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianDepthAwareV.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(0.0, 1.0), getViewportInvWidthHeight());\n}\n\n\n\n" }, - "uo82ZPhCcJxhWNrApR0XKA==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_lightmap_normal_map.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_lightmap_normal_map.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n", - "type": 36385 + "OXuYqz7HXHKCvj2UC5LgYg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor0;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb + fadeEmissive, colorAlpha * texel.a);\n}\n\n" }, - "voH5uVQG4oY2u7HBLBjCcg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_fade.slv\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// model_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n packDeferredFragmentUnlit(\n normalize(_normalWS), \n opacity,\n albedo * isUnlitEnabled());\n}\n\n\n", - "type": 36385 + "Ok9iZWcsGL4q0bLcSA15DQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "wrkiMXQFABfKlr/1MNNU5A==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:59 2018\n//\n// simple_transparent_web_browser.slf\n// fragment shader\n//\n// Created by Anthony Thibault on 7/25/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n\n\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:59 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n\n\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n texel = color_sRGBAToLinear(texel);\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n _color.a,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n}\n\n\n", - "type": 36385 + "OnbojG95NhmpyDQOx0iTzQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" }, - "wyCwvi533Oyk8ufIQbVrxg==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionES;\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "OrApvS3xLxHRsw+fYw1FGg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_textured_unlit.frag\n// fragment shader\n//\n// Created by Clement Brisset on 5/29/15.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n\n const float ALPHA_THRESHOLD = 0.999;\n if (colorAlpha * texel.a < ALPHA_THRESHOLD) {\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha * texel.a,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n } else {\n packDeferredFragmentUnlit(\n normalize(_normalWS),\n 1.0,\n _color.rgb * texel.rgb);\n }\n}\n\n" }, - "xeeuuc9UWZQq1G+CHZOaXQ==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n\n\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0;\nlayout(location = 1) out vec4 _fragColor1;\nlayout(location = 2) out vec4 _fragColor2;\n\nlayout(location = 3) out vec4 _fragColor3;\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec3 _normalWS;\nin vec3 _color;\nin vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n\n\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n", - "type": 36385 + "P6OwkvLRGTZTEznF6VYYzw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec4 _positionWS;\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" }, - "yX+x8ZXYN2FZ8fFX2rGHRw==": { - "source": "//-------- 0\n\n//PC 410 core\n// Generated on Tue May 22 11:51:57 2018\n// model_fade.slv\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- 1\n\n//PC 410 core\n// Generated on Tue May 22 11:51:58 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nflat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nflat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Tue May 22 11:51:58 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n\n\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n", - "type": 36385 + "PenRxjxfyu6BZ1zAlxzVsg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "PpGze5SXPBQ8cU4OIPl3iQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "PvKsMxZ7XmmybJMzNJjbQg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "QFC2mrxkRobv+zJiIHMbUA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec4 _positionWS;\n\nvoid main(void) {\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "QK0w4Yh9tGTneCM+4XmuWQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "Qjow7Vm0FAyIwkizx143yA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_ambient_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n\n\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n \n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "QolYhWOxFZg7j6BuKVTkNA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "RBD7sDmFLNuS6SYIBsx+hQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_ambient_light.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 9/3/14.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n _fragColor = vec4(color, 1.0);\n\n }\n}\n\n\n" + }, + "RjdepXqRdX+qe5lSXqd2qA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// local_lights_shading.frag\n// fragment shader\n//\n// Created by Sam Gateau on 9/6/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about deferred buffer\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\n\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform lightBuffer {\n\n\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n\n\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n\n\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}in vec2 _texCoord0;\nout vec4 _fragColor;\n\nvoid main(void) {\n _fragColor = vec4(0.0);\n\n // Grab the fragment data from the uv\n vec2 texCoord = _texCoord0.st;\n\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n\n\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord);\n vec4 fragPosition = frag.position;\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n }\n\n // Frag pos in world\n mat4 invViewMat = getViewInverse();\n vec4 fragWorldPos = invViewMat * fragPosition;\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (!hasLocalLights(numLights, clusterPos, dims)) {\n discard;\n }\n\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);\n }\n\n\n // Frag to eye vec\n vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);\n vec3 fragEyeDir = normalize(fragEyeVector.xyz);\n SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir);\n\n _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface, \n frag.metallic, frag.fresnel, frag.albedo, frag.scattering, \n midNormalCurvature, lowNormalCurvature, 1.0);\n\n}\n\n\n\n" + }, + "RvmQNF6dKH4aQ6NwzXCEkA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// velocityBuffer_cameraMotion.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D depthMap;\n\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n \n\tfloat Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;\n\n\t// The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalUnjitteredEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);\n\tvec3 worldPos = (getViewInverse() * vec4(eyePos, 1.0)).xyz;\n \n vec3 prevEyePos = (getPreviousView() * vec4(worldPos, 1.0)).xyz;\n vec4 prevClipPos = (getUnjitteredProjection(stereoSide.x) * vec4(prevEyePos, 1.0));\n vec2 prevUV = 0.5 * (prevClipPos.xy / prevClipPos.w) + vec2(0.5);\n\n //vec2 imageSize = getWidthHeight(0);\n vec2 imageSize = vec2(1.0, 1.0);\n outFragColor = vec4( ((texcoordPos - prevUV) * imageSize), 0.0, 0.0);\n}\n\n\n" + }, + "U/JRfxWikaERXEtfd3D7iw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// skin_model_shadow_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "UtSPZV6j2V+sfW5h8VKzdQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// taa.frag\n// fragment shader\n//\n// Created by Sam Gateau on 8/14/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// TAA.slh\n// Common component needed by TemporalAntialiasing fragment shader\n//\n// Created by Sam Gateau on 8/17/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nuniform sampler2D depthMap;\nuniform sampler2D sourceMap;\nuniform sampler2D historyMap;\nuniform sampler2D velocityMap;\nuniform sampler2D nextMap;\n\nstruct TAAParams\n{\n\tfloat none;\n\tfloat blend;\n\tfloat covarianceGamma;\n\tfloat debugShowVelocityThreshold;\n ivec4 flags;\n vec4 pixelInfo_orbZoom;\n vec4 regionInfo;\n};\n\nlayout(std140) uniform taaParamsBuffer {\n TAAParams params;\n};\n\n#define GET_BIT(bitfield, bitIndex) bool((bitfield) & (1 << (bitIndex)))\n\nbool taa_isDebugEnabled() {\n return GET_BIT(params.flags.x, 0);\n}\n\nbool taa_showDebugCursor() {\n return GET_BIT(params.flags.x, 1);\n}\n\nbool taa_showClosestFragment() {\n return GET_BIT(params.flags.x, 3);\n}\n\nbool taa_constrainColor() {\n return GET_BIT(params.flags.y, 1);\n}\n\nbool taa_feedbackColor() {\n return GET_BIT(params.flags.y, 4);\n}\n\nvec2 taa_getDebugCursorTexcoord() {\n return params.pixelInfo_orbZoom.xy;\n}\n\nfloat taa_getDebugOrbZoom() {\n return params.pixelInfo_orbZoom.z;\n}\n\nvec2 taa_getRegionDebug() {\n return params.regionInfo.xy;\n}\n\nvec2 taa_getRegionFXAA() {\n return params.regionInfo.zw;\n}\n#define USE_YCOCG 1\n\nvec4 taa_fetchColor(sampler2D map, vec2 uv) {\n\tvec4 c = texture(map, uv);\n\t// Apply rapid pseudo tonemapping as TAA is applied to a tonemapped image, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),c.rgb);\n\tc.rgb = c.rgb / (1.0+lum);\n#if USE_YCOCG\n\treturn vec4(color_LinearToYCoCg(c.rgb), c.a);\n#else\n\treturn c;\n#endif\n}\n\nvec3 taa_resolveColor(vec3 color) {\n#if USE_YCOCG\n\tcolor = max(vec3(0), color_YCoCgToUnclampedLinear(color));\n#endif\n\t// Apply rapid inverse tonemapping, using luminance as weight, as proposed in\n\t// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf\n\tfloat lum = dot(vec3(0.3,0.5,0.2),color.rgb);\n\tcolor = color / (1.0-lum);\n\treturn color;\n}\n\nvec4 taa_fetchSourceMap(vec2 uv) {\n\treturn taa_fetchColor(sourceMap, uv);\n}\n\nvec4 taa_fetchHistoryMap(vec2 uv) {\n\treturn taa_fetchColor(historyMap, uv);\n}\n\nvec4 taa_fetchNextMap(vec2 uv) {\n\treturn taa_fetchColor(nextMap, uv);\n}\n\nvec2 taa_fetchVelocityMap(vec2 uv) {\n\treturn texture(velocityMap, uv).xy;\n}\n\nfloat taa_fetchDepth(vec2 uv) {\n\treturn -texture(depthMap, vec2(uv), 0).x;\n}\n\n\n#define ZCMP_GT(a, b) (a > b)\n\nvec2 taa_getImageSize() {\n vec2 imageSize = getWidthHeight(0);\n if (isStereo()) {\n imageSize.x *= 2.0;\n }\n return imageSize;\n}\n\nvec2 taa_getTexelSize() {\n vec2 texelSize = getInvWidthHeight();\n if (isStereo()) {\n texelSize.x *= 0.5;\n }\n return texelSize;\n}\n\nvec3 taa_findClosestFragment3x3(vec2 uv)\n{\n\tvec2 dd = abs(taa_getTexelSize());\n\tvec2 du = vec2(dd.x, 0.0);\n\tvec2 dv = vec2(0.0, dd.y);\n\n\tvec3 dtl = vec3(-1, -1, taa_fetchDepth(uv - dv - du));\n\tvec3 dtc = vec3( 0, -1, taa_fetchDepth(uv - dv));\n\tvec3 dtr = vec3( 1, -1, taa_fetchDepth(uv - dv + du));\n\n\tvec3 dml = vec3(-1, 0, taa_fetchDepth(uv - du));\n\tvec3 dmc = vec3( 0, 0, taa_fetchDepth(uv));\n\tvec3 dmr = vec3( 1, 0, taa_fetchDepth(uv + du));\n\n\tvec3 dbl = vec3(-1, 1, taa_fetchDepth(uv + dv - du));\n\tvec3 dbc = vec3( 0, 1, taa_fetchDepth(uv + dv));\n\tvec3 dbr = vec3( 1, 1, taa_fetchDepth(uv + dv + du));\n\n\tvec3 dmin = dtl;\n\tif (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc;\n\tif (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr;\n\n\tif (ZCMP_GT(dmin.z, dml.z)) dmin = dml;\n\tif (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc;\n\tif (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr;\n\n\tif (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl;\n\tif (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc;\n\n\n\tif (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr;\n\n\treturn vec3(uv + dd.xy * dmin.xy, dmin.z);\n}\n\nvec2 taa_fetchVelocityMapBest(vec2 uv) {\n vec2 dd = abs(taa_getTexelSize());\n vec2 du = vec2(dd.x, 0.0);\n vec2 dv = vec2(0.0, dd.y);\n\n vec2 dtl = taa_fetchVelocityMap(uv - dv - du);\n vec2 dtc = taa_fetchVelocityMap(uv - dv);\n vec2 dtr = taa_fetchVelocityMap(uv - dv + du);\n\n vec2 dml = taa_fetchVelocityMap(uv - du);\n vec2 dmc = taa_fetchVelocityMap(uv);\n vec2 dmr = taa_fetchVelocityMap(uv + du);\n\n vec2 dbl = taa_fetchVelocityMap(uv + dv - du);\n vec2 dbc = taa_fetchVelocityMap(uv + dv);\n vec2 dbr = taa_fetchVelocityMap(uv + dv + du);\n\n vec3 best = vec3(dtl, dot(dtl,dtl));\n\n float testSpeed = dot(dtc,dtc);\n if (testSpeed > best.z) { best = vec3(dtc, testSpeed); }\n testSpeed = dot(dtr,dtr);\n if (testSpeed > best.z) { best = vec3(dtr, testSpeed); }\n\n testSpeed = dot(dml,dml);\n if (testSpeed > best.z) { best = vec3(dml, testSpeed); }\n testSpeed = dot(dmc,dmc);\n if (testSpeed > best.z) { best = vec3(dmc, testSpeed); }\n testSpeed = dot(dmr,dmr);\n if (testSpeed > best.z) { best = vec3(dmr, testSpeed); }\n\n testSpeed = dot(dbl,dbl);\n if (testSpeed > best.z) { best = vec3(dbl, testSpeed); }\n testSpeed = dot(dbc,dbc);\n if (testSpeed > best.z) { best = vec3(dbc, testSpeed); }\n testSpeed = dot(dbr,dbr);\n if (testSpeed > best.z) { best = vec3(dbr, testSpeed); }\n\n return best.xy;\n}\n\nvec2 taa_fromFragUVToEyeUVAndSide(vec2 fragUV, out int stereoSide) {\n vec2 eyeUV = fragUV;\n stereoSide = 0;\n if (isStereo()) {\n if (eyeUV.x > 0.5) {\n eyeUV.x -= 0.5;\n stereoSide = 1;\n }\n eyeUV.x *= 2.0;\n }\n return eyeUV;\n}\n\nvec2 taa_fromEyeUVToFragUV(vec2 eyeUV, int stereoSide) {\n vec2 fragUV = eyeUV;\n if (isStereo()) {\n fragUV.x *= 0.5;\n fragUV.x += stereoSide*0.5;\n }\n return fragUV;\n}\n\nvec2 taa_computePrevFragAndEyeUV(vec2 fragUV, vec2 fragVelocity, out vec2 prevEyeUV) {\n int stereoSide = 0;\n vec2 eyeUV = taa_fromFragUVToEyeUVAndSide(fragUV, stereoSide);\n prevEyeUV = eyeUV - fragVelocity;\n return taa_fromEyeUVToFragUV(prevEyeUV, stereoSide);\n}\n\nvec2 taa_fetchSourceAndHistory(vec2 fragUV, vec2 fragVelocity, out vec3 sourceColor, out vec3 historyColor) {\n vec2 prevEyeUV;\n vec2 prevFragUV = taa_computePrevFragAndEyeUV(fragUV, fragVelocity, prevEyeUV);\n sourceColor = taa_fetchSourceMap(fragUV).xyz;\n\n historyColor = sourceColor;\n if (!(any(lessThan(prevEyeUV, vec2(0.0))) || any(greaterThan(prevEyeUV, vec2(1.0))))) {\n historyColor = taa_fetchHistoryMap(prevFragUV).xyz;\n }\n return prevFragUV;\n}\n\nfloat Luminance(vec3 rgb) {\n return rgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0;\n}\n\n#define MINMAX_3X3_ROUNDED 1\n\nmat3 taa_evalNeighbourColorVariance(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity) {\n vec2 texelSize = taa_getTexelSize();\n \n\n\tvec2 du = vec2(texelSize.x, 0.0);\n\tvec2 dv = vec2(0.0, texelSize.y);\n\n vec3 sampleColor = taa_fetchSourceMap(fragUV - dv - du).rgb;\n vec3 sumSamples = sampleColor;\n vec3 sumSamples2 = sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sampleColor isn't it ?\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv - du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n sampleColor = taa_fetchSourceMap(fragUV + dv).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n \n sampleColor = taa_fetchSourceMap(fragUV + dv + du).rgb;\n sumSamples += sampleColor;\n sumSamples2 += sampleColor * sampleColor;\n\n \n vec3 mu = sumSamples / vec3(9.0);\n vec3 sigma = sqrt(max(sumSamples2 / vec3(9.0) - mu * mu, vec3(0.0)));\n \n float gamma = params.covarianceGamma;\n vec3 cmin = mu - gamma * sigma;\n vec3 cmax = mu + gamma * sigma;\n\n return mat3(cmin, cmax, mu);\n}\n\nmat3 taa_evalNeighbourColorRegion(vec3 sourceColor, vec2 fragUV, vec2 fragVelocity, float fragZe) {\n vec2 imageSize = taa_getImageSize();\n vec2 texelSize = taa_getTexelSize();\n vec3 cmin, cmax, cavg;\n\n #if MINMAX_3X3_ROUNDED\n\t\tvec2 du = vec2(texelSize.x, 0.0);\n\t\tvec2 dv = vec2(0.0, texelSize.y);\n\n\t\tvec3 ctl = taa_fetchSourceMap(fragUV - dv - du).rgb;\n\t\tvec3 ctc = taa_fetchSourceMap(fragUV - dv).rgb;\n\t\tvec3 ctr = taa_fetchSourceMap(fragUV - dv + du).rgb;\n\t\tvec3 cml = taa_fetchSourceMap(fragUV - du).rgb;\n\t\tvec3 cmc = sourceColor; //taa_fetchSourceMap(fragUV).rgb; // could resuse the same osurce sample isn't it ?\n\t\tvec3 cmr = taa_fetchSourceMap(fragUV + du).rgb;\n\t\tvec3 cbl = taa_fetchSourceMap(fragUV + dv - du).rgb;\n\t\tvec3 cbc = taa_fetchSourceMap(fragUV + dv).rgb;\n\t\tvec3 cbr = taa_fetchSourceMap(fragUV + dv + du).rgb;\n\n\t\tcmin = min(ctl, min(ctc, min(ctr, min(cml, min(cmc, min(cmr, min(cbl, min(cbc, cbr))))))));\n\t\tcmax = max(ctl, max(ctc, max(ctr, max(cml, max(cmc, max(cmr, max(cbl, max(cbc, cbr))))))));\n\n\t\t#if MINMAX_3X3_ROUNDED || USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (ctl + ctc + ctr + cml + cmc + cmr + cbl + cbc + cbr) / 9.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n\n\t\t#if MINMAX_3X3_ROUNDED\n\t\t\tvec3 cmin5 = min(ctc, min(cml, min(cmc, min(cmr, cbc))));\n\t\t\tvec3 cmax5 = max(ctc, max(cml, max(cmc, max(cmr, cbc))));\n\t\t\tvec3 cavg5 = (ctc + cml + cmc + cmr + cbc) / 5.0;\n\t\t\tcmin = 0.5 * (cmin + cmin5);\n\t\t\tcmax = 0.5 * (cmax + cmax5);\n\t\t\tcavg = 0.5 * (cavg + cavg5);\n\t\t#endif\n #else\n\t\tconst float _SubpixelThreshold = 0.5;\n\t\tconst float _GatherBase = 0.5;\n\t\tconst float _GatherSubpixelMotion = 0.1666;\n\n\t\tvec2 texel_vel = fragVelocity * imageSize;\n\t\tfloat texel_vel_mag = length(texel_vel) * -fragZe;\n\t\tfloat k_subpixel_motion = clamp(_SubpixelThreshold / (0.0001 + texel_vel_mag), 0.0, 1.0);\n\t\tfloat k_min_max_support = _GatherBase + _GatherSubpixelMotion * k_subpixel_motion;\n\n\t\tvec2 ss_offset01 = k_min_max_support * vec2(-texelSize.x, texelSize.y);\n\t\tvec2 ss_offset11 = k_min_max_support * vec2(texelSize.x, texelSize.y);\n\t\tvec3 c00 = taa_fetchSourceMap(fragUV - ss_offset11).rgb;\n\t\tvec3 c10 = taa_fetchSourceMap(fragUV - ss_offset01).rgb;\n\t\tvec3 c01 = taa_fetchSourceMap(fragUV + ss_offset01).rgb;\n\t\tvec3 c11 = taa_fetchSourceMap(fragUV + ss_offset11).rgb;\n\n\t\tcmin = min(c00, min(c10, min(c01, c11)));\n\t\tcmax = max(c00, max(c10, max(c01, c11)));\n cavg = (cmin + cmax ) * 0.5;\n\n\t\t#if USE_YCOCG || USE_CLIPPING\n\t\t\tcavg = (c00 + c10 + c01 + c11) / 4.0;\n #elif\n cavg = (cmin + cmax ) * 0.5;\n\t\t#endif\n #endif\n\n \t\t// shrink chroma min-max\n\t#if USE_YCOCG\n\t\tvec2 chroma_extent = vec2(0.25 * 0.5 * (cmax.r - cmin.r));\n\t\tvec2 chroma_center = sourceColor.gb;\n\t\tcmin.yz = chroma_center - chroma_extent;\n\t\tcmax.yz = chroma_center + chroma_extent;\n\t\tcavg.yz = chroma_center;\n\t#endif\n\n return mat3(cmin, cmax, cavg);\n}\n\n//#define USE_OPTIMIZATIONS 0\n\nvec3 taa_clampColor(vec3 colorMin, vec3 colorMax, vec3 colorSource, vec3 color) {\n\tconst float eps = 0.00001;\n vec3 p = colorSource;\n vec3 q = color;\n\t// note: only clips towards aabb center (but fast!)\n\tvec3 p_clip = 0.5 * (colorMax + colorMin);\n\tvec3 e_clip = 0.5 * (colorMax - colorMin) + vec3(eps);\n\n\tvec3 v_clip = q - p_clip;\n\tvec3 v_unit = v_clip.xyz / e_clip;\n\tvec3 a_unit = abs(v_unit);\n\tfloat ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z));\n\n\tif (ma_unit > 1.0)\n\t\treturn p_clip + v_clip / ma_unit;\n\telse\n\t\treturn q;// point inside aabb\t\t\n}\n\nvec3 taa_evalConstrainColor(vec3 sourceColor, vec2 sourceUV, vec2 sourceVel, vec3 candidateColor) {\n mat3 colorMinMaxAvg;\n\n colorMinMaxAvg = taa_evalNeighbourColorVariance(sourceColor, sourceUV, sourceVel);\n \n\t// clamp history to neighbourhood of current sample\n return taa_clampColor(colorMinMaxAvg[0], colorMinMaxAvg[1], sourceColor, candidateColor);\n}\n\nvec3 taa_evalFeedbackColor(vec3 sourceColor, vec3 historyColor, float blendFactor) {\n const float _FeedbackMin = 0.1;\n const float _FeedbackMax = 0.9;\n\t// feedback weight from unbiased luminance diff (t.lottes)\n\t#if USE_YCOCG\n\t\tfloat lum0 = sourceColor.r;\n\t\tfloat lum1 = historyColor.r;\n\t#else\n\t\tfloat lum0 = Luminance(sourceColor.rgb);\n\t\tfloat lum1 = Luminance(historyColor.rgb);\n\t#endif\n\tfloat unbiased_diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));\n\tfloat unbiased_weight = 1.0 - unbiased_diff;\n\tfloat unbiased_weight_sqr = unbiased_weight * unbiased_weight;\n\tfloat k_feedback = mix(_FeedbackMin, _FeedbackMax, unbiased_weight_sqr);\n\n \n vec3 nextColor = mix(historyColor, sourceColor, k_feedback * blendFactor).xyz;\n return nextColor;\n}\n\n\nvec3 colorWheel(float normalizedHue) {\n float v = normalizedHue * 6.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n } else if (v < 2.f) {\n return vec3(1.f - (v-1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v-2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v-3.f), 1.f );\n } else if (v < 5.f) {\n return vec3((v-4.f), 0.f, 1.f );\n } else if (v < 6.f) {\n return vec3(1.f, 0.f, 1.f - (v-5.f));\n } else {\n return vec3(1.f, 0.f, 0.f);\n }\n}\n\nvec3 colorRamp(float normalizedHue) {\n float v = normalizedHue * 5.f;\n if (v < 0.f) {\n return vec3(1.f, 0.f, 0.f);\n } else if (v < 1.f) {\n return vec3(1.f, v, 0.f);\n\n\n } else if (v < 2.f) {\n return vec3(1.f - (v - 1.f), 1.f, 0.f);\n } else if (v < 3.f) {\n return vec3(0.f, 1.f, (v - 2.f));\n } else if (v < 4.f) {\n return vec3(0.f, 1.f - (v - 3.f), 1.f);\n } else if (v < 5.f) {\n return vec3((v - 4.f), 0.f, 1.f);\n } else {\n return vec3(1.f, 0.f, 1.f);\n }\n}\n\n\nvec3 taa_getVelocityColorRelative(float velocityPixLength) {\n return colorRamp(velocityPixLength/params.debugShowVelocityThreshold);\n}\n\nvec3 taa_getVelocityColorAboveThreshold(float velocityPixLength) {\n return colorRamp((velocityPixLength - params.debugShowVelocityThreshold)/params.debugShowVelocityThreshold);\n}\n\n\nvec3 taa_evalFXAA(vec2 fragUV) {\n\n // vec2 texelSize = getInvWidthHeight();\n vec2 texelSize = taa_getTexelSize();\n\n // filter width limit for dependent \"two-tap\" texture samples\n float FXAA_SPAN_MAX = 8.0;\n\n // local contrast multiplier for performing AA\n // higher = sharper, but setting this value too high will cause near-vertical and near-horizontal edges to fail\n // see \"fxaaQualityEdgeThreshold\"\n float FXAA_REDUCE_MUL = 1.0 / 8.0;\n\n // luminance threshold for processing dark colors\n // see \"fxaaQualityEdgeThresholdMin\"\n float FXAA_REDUCE_MIN = 1.0 / 128.0;\n\n // fetch raw RGB values for nearby locations\n // sampling pattern is \"five on a die\" (each diagonal direction and the center)\n // computing the coordinates for these texture reads could be moved to the vertex shader for speed if needed\n vec3 rgbNW = texture(sourceMap, fragUV + (vec2(-1.0, -1.0) * texelSize)).xyz;\n vec3 rgbNE = texture(sourceMap, fragUV + (vec2(+1.0, -1.0) * texelSize)).xyz;\n vec3 rgbSW = texture(sourceMap, fragUV + (vec2(-1.0, +1.0) * texelSize)).xyz;\n vec3 rgbSE = texture(sourceMap, fragUV + (vec2(+1.0, +1.0) * texelSize)).xyz;\n vec3 rgbM = texture(sourceMap, fragUV).xyz;\n\t\n // convert RGB values to luminance\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot( rgbM, luma);\n\t\n // luma range of local neighborhood\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\t\n // direction perpendicular to local luma gradient\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n // compute clamped direction offset for additional \"two-tap\" samples\n // longer vector = blurry, shorter vector = sharp\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), \n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize;\n\t\t\n // perform additional texture sampling perpendicular to gradient\n vec3 rgbA = (1.0 / 2.0) * (\n texture(sourceMap, fragUV + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (\n texture(sourceMap, fragUV + dir * (0.0 / 3.0 - 0.5)).xyz +\n texture(sourceMap, fragUV + dir * (3.0 / 3.0 - 0.5)).xyz);\n float lumaB = dot(rgbB, luma);\n\n // compare luma of new samples to the luma range of the original neighborhood\n // if the new samples exceed this range, just use the first two samples instead of all four\n if (lumaB < lumaMin || lumaB > lumaMax) {\n return rgbA;\n } else {\n return rgbB;\n }\n}in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main() {\n vec2 fragUV = varTexCoord0;\n\n // Debug region before debug or fxaa region X\n float distToRegionFXAA = fragUV.x - taa_getRegionFXAA().x; \n if (distToRegionFXAA > 0.0) {\n outFragColor = vec4(taa_evalFXAA(fragUV), 1.0);\n return;\n }\n\n vec2 fragVel = taa_fetchVelocityMapBest(fragUV).xy;\n\n vec3 sourceColor;\n vec3 historyColor;\n vec2 prevFragUV = taa_fetchSourceAndHistory(fragUV, fragVel, sourceColor, historyColor);\n\n vec3 nextColor = sourceColor;\n \n if (taa_constrainColor()) {\n // clamp history to neighbourhood of current sample\n historyColor = taa_evalConstrainColor(sourceColor, fragUV, fragVel, historyColor);\n }\n \n if (taa_feedbackColor()) {\n nextColor = taa_evalFeedbackColor(sourceColor, historyColor, params.blend);\n } else {\n nextColor = mix(historyColor, sourceColor, params.blend);\n }\n\n outFragColor = vec4(taa_resolveColor(nextColor), 1.0);\n}\n\n\n" + }, + "VTnPMaIDQTsMllfsMr5Tew==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_skybox_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//!>\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\n\n\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "VW6Abw5AzhHt52D7YLE4Ww==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "VezxukUuV2VczJFSW6hvGg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D_model_transparent.frag\n//\n// Created by Sam Gateau on 2/27/2017.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n\n\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPosition = _positionES.xyz;\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n emissive,\n roughness, opacity),\n opacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n" + }, + "W+HP2v/b3aXW0UJd68rbWw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "W6lqpCKxUv9XryZ58YFYKw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor0;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb + fadeEmissive, colorAlpha * texel.a);\n}\n\n" + }, + "WaR4mMRDZuwrtZeKHhYcYQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// standardTransformPNTC.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/10/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 varPosition;\nout vec3 varNormal;\nout vec2 varTexCoord0;\nout vec4 varColor;\n\nvoid main(void) {\n varTexCoord0 = inTexCoord0.st;\n varColor = color_sRGBAToLinear(inColor);\n \n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n varNormal = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n varPosition = inPosition.xyz;\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTextureOpaque.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n// Alpha is 1\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(texture(colorMap, varTexCoord0).xyz, 1.0);\n}\n\n\n" + }, + "WbmSQgBwTA31eDChQObMLQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D_model_transparent.frag\n//\n// Created by Sam Gateau on 2/27/2017.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n\n\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPosition = _positionES.xyz;\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n emissive,\n roughness, opacity),\n opacity);\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n" + }, + "XK3QC6wS+A9lXJNuiydI8Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n\n\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n\n\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\nvec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {\n\n // Need the light now\n Light light = getKeyLight();\n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n LightAmbient ambient = getLightAmbient();\n\n TransformCamera cam = getTransformCamera();\n vec3 fragEyeVectorView = normalize(-position);\n vec3 fragEyeDir;\n { // transformEyeToWorldDir\n fragEyeDir = vec3(cam._viewInverse * vec4(fragEyeVectorView.xyz, 0.0));\n }\n\n\n SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);\n\n vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled();\n color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled();\n\n return vec4(color, opacity);\n}\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n vec3 fragAlbedo = albedo.rgb * _color;\n float fragMetallic = 0.0;\n vec3 fragSpecular = vec3(0.1);\n float fragRoughness = 0.9;\n float fragOpacity = albedo.a;\n\n if (fragOpacity <= 0.1) {\n discard;\n }\n\n vec4 color = evalGlobalColor(1.0,\n fragPosition,\n fragNormal,\n fragAlbedo,\n fragMetallic,\n fragSpecular,\n fragRoughness,\n fragOpacity);\n\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n\n" + }, + "YRhR/TtZ3TB+GLUSmpfmXw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent.vert\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "ZDrgpFTPVfPS6hdGXRwS4g==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n\n\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "ZFdSYNQ583QSXI16YpjAjg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianDepthAwareV.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(0.0, 1.0), getViewportInvWidthHeight());\n}\n\n\n\n" + }, + "ZeGPkhGlT/ymBXA0jFFamw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianDepthAwareH.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\nuniform sampler2D depthMap;\n\nvec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n float sampleDepth = texture(depthMap, texcoord).x;\n if (sampleDepth >= getPosLinearDepthFar()) {\n discard;\n }\n vec4 sampleCenter = texture(sourceMap, texcoord);\n\n // Calculate the width scale.\n float distanceToProjectionWindow = getDepthPerspective();\n\n float depthThreshold = getDepthThreshold();\n\n // Calculate the final step to fetch the surrounding pixels.\n float filterScale = getFilterScale();\n float scale = distanceToProjectionWindow / sampleDepth;\n\n vec2 finalStep = filterScale * scale * direction * pixelStep;\n int numTaps = getFilterNumTaps();\n\n // Accumulate the center sample\n vec2 tapInfo = getFilterTap(0);\n float totalWeight = getFilterTapWeight(tapInfo);\n vec4 srcBlurred = sampleCenter * totalWeight;\n\n for(int i = 1; i < numTaps; i++) {\n tapInfo = getFilterTap(i);\n\n // Fetch color and depth for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n float srcDepth = texture(depthMap, sampleCoord).x;\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n \n // If the difference in depth is huge, we lerp color back.\n float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);\n srcSample = mix(srcSample, sampleCenter, s);\n\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n } \n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n return srcBlurred;\n}\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussianDepthAware(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n" + }, + "ZezT7IYThMJrsNlMn12WVw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// skin_model_shadow_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\n\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "aDHkDPH8eyY9e3nPkAsVJA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_unlit_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n\n\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n albedo += fadeEmissive;\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n" + }, + "ac/KNw/7IqiVu8234N//SQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeSpecularBeckmann.frag\n//\n// Created by Sam Gateau on 6/30/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nfloat specularBeckmann(float ndoth, float roughness) {\n float alpha = acos(ndoth);\n float ta = tan(alpha);\n float val = 1.0 / (roughness * roughness * pow(ndoth, 4.0)) * exp(-(ta * ta) / (roughness * roughness));\n return val;\n}\n\nvoid main(void) {\n outFragColor = vec4(vec3(0.5 * pow( specularBeckmann(varTexCoord0.x, varTexCoord0.y), 0.1)), 1.0);\n}\n\n\n" + }, + "aczRujxXj+aRYhb9b147Dg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent_normal_map.vert\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "bB6y3KjzOm6CAmU3y7PcWQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_ambient_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n\n\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\nvec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalAmbientSphereGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n \n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "bQwmNhUUAqzPWpHuwpBapw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_skybox_light.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/8/2015.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "bwGVwYvJmCg8vJFz7IoMGA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "c+ZrVo/zLabK7DoATVqlzQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:43 2018\n//\n// blurGaussianH.frag\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Sam Gateau on 6/7/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:23:43 2018\n//\n// Created by Olivier Prat on 09/25/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n#define BLUR_MAX_NUM_TAPS 33\nstruct BlurParameters {\n vec4 resolutionInfo;\n vec4 texcoordTransform;\n vec4 filterInfo;\n vec4 depthInfo;\n vec4 stereoInfo;\n vec4 linearDepthInfo;\n vec2 taps[BLUR_MAX_NUM_TAPS];\n};\n\nuniform blurParamsBuffer {\n BlurParameters parameters;\n};\n\nvec2 getViewportInvWidthHeight() {\n return parameters.resolutionInfo.zw;\n}\n\nvec2 evalTexcoordTransformed(vec2 texcoord) {\n return (texcoord * parameters.texcoordTransform.zw + parameters.texcoordTransform.xy);\n}\n\nfloat getFilterScale() {\n return parameters.filterInfo.x;\n}\n\nint getFilterNumTaps() {\n return int(parameters.filterInfo.y);\n}\n\nfloat getOutputAlpha() {\n return parameters.filterInfo.z;\n}\n\nvec2 getFilterTap(int index) {\n return parameters.taps[index];\n}\n\nfloat getFilterTapOffset(vec2 tap) {\n return tap.x;\n}\n\nfloat getFilterTapWeight(vec2 tap) {\n return tap.y;\n}\n\nfloat getDepthThreshold() {\n return parameters.depthInfo.x;\n}\n\nfloat getDepthPerspective() {\n return parameters.depthInfo.w;\n}\n\nfloat getPosLinearDepthFar() {\n return parameters.linearDepthInfo.x;\n}\n\n\n\nuniform sampler2D sourceMap;\n\nvec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) {\n texcoord = evalTexcoordTransformed(texcoord);\n\n vec2 finalStep = getFilterScale() * direction * pixelStep;\n vec4 srcBlurred = vec4(0.0);\n float totalWeight = 0.f;\n int numTaps = getFilterNumTaps();\n \n for(int i = 0; i < numTaps; i++) {\n vec2 tapInfo = getFilterTap(i);\n // Fetch color for current sample.\n vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep);\n if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) {\n vec4 srcSample = texture(sourceMap, sampleCoord);\n float weight = getFilterTapWeight(tapInfo);\n // Accumulate.\n srcBlurred += srcSample * weight;\n totalWeight += weight;\n }\n }\n \n if (totalWeight>0.0) {\n srcBlurred /= totalWeight;\n }\n srcBlurred.a = getOutputAlpha();\n return srcBlurred;\n}\n\n\n\n\nlayout(location = 0) in vec2 varTexCoord0;\n\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = pixelShaderGaussian(varTexCoord0, vec2(1.0, 0.0), getViewportInvWidthHeight());\n}\n\n\n\n" + }, + "cOLui+erS7m5I6glwc2H/A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeProfile.frag\n//\n// Created by Sam Gateau on 6/27/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\n\nvec3 generateProfile(vec2 uv) {\n return scatter(uv.x * 2.0);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(generateProfile(varTexCoord0.xy), 1.0);\n}\n\n\n" + }, + "cuqklOIZ4d1AGklaKR2C0Q==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/08/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "d4HgeNo/bw1nDnwvLEqa0g==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "dAktKesn7UY7+h6sq47y3w==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent.vert\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "dhhvXoOvTtCA5UTcdZK1+g==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_normal_map.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_normal_map.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n" + }, + "dnlqL9nMiIkDsF1B+zt2dw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n _fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha);\n}\n\n\n" + }, + "e0Pe74cfrY87BUGhMWpd+A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_skybox_light_shadow.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 1/18/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//!>\n\n// glsl / C++ compatible source as interface for Shadows\n#ifdef __cplusplus\n# define MAT4 glm::mat4\n#else\n# define MAT4 mat4\n#endif\n\n#define SHADOW_CASCADE_MAX_COUNT 4\n\nstruct ShadowTransform {\n\tMAT4 reprojection;\n\tfloat fixedBias;\n float slopeBias;\n float _padding1;\n float _padding2;\n};\n\nstruct ShadowParameters {\n ShadowTransform cascades[SHADOW_CASCADE_MAX_COUNT];\n int cascadeCount;\n float invMapSize;\n float invCascadeBlendWidth;\n float maxDistance;\n float invFalloffDistance;\n};\n\n// //\nlayout(std140) uniform shadowTransformBuffer {\n\tShadowParameters shadow;\n};\n\nint getShadowCascadeCount() {\n return shadow.cascadeCount;\n}\n\nfloat getShadowCascadeInvBlendWidth() {\n return shadow.invCascadeBlendWidth;\n}\n\nfloat evalShadowFalloff(float depth) {\n return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0);\n}\n\nmat4 getShadowReprojection(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].reprojection;\n}\n\nfloat getShadowScale() {\n\treturn shadow.invMapSize;\n}\n\nfloat getShadowFixedBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].fixedBias;\n}\n\nfloat getShadowSlopeBias(int cascadeIndex) {\n\treturn shadow.cascades[cascadeIndex].slopeBias;\n}\n\n\n// Compute the texture coordinates from world coordinates\nvec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {\n\tvec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;\n\treturn vec4(shadowCoord.xyz, 1.0);\n}\n\nbool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {\n bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0));\n bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1));\n return all(greaterThanZero) && all(lessThanOne);\n}\n\nint getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) {\n int cascadeIndex;\n startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1);\n for (cascadeIndex=startCascadeIndex ; cascadeIndex> 1;\n#endif\n\n // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html\n ivec2 offset = coords & ivec2(1,1);\n offset.y = (offset.x+offset.y) & 1;\n\n offsets.points[0] = shadowScale * vec3(offset + PCFkernel[0], 0.0);\n offsets.points[1] = shadowScale * vec3(offset + PCFkernel[1], 0.0);\n offsets.points[2] = shadowScale * vec3(offset + PCFkernel[2], 0.0);\n offsets.points[3] = shadowScale * vec3(offset + PCFkernel[3], 0.0);\n\n return offsets;\n}\n\nfloat evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float bias) {\n shadowTexcoord.z -= bias;\n float shadowAttenuation = 0.25 * (\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[0]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[1]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[2]) +\n fetchShadow(cascadeIndex, shadowTexcoord.xyz + offsets.points[3])\n );\n return shadowAttenuation;\n}\n\nfloat evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {\n float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;\n return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);\n}\n\nfloat evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {\n ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);\n vec4 cascadeShadowCoords[2];\n cascadeShadowCoords[0] = vec4(0);\n cascadeShadowCoords[1] = vec4(0);\n ivec2 cascadeIndices;\n float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);\n\t\n // Adjust bias if we are at a grazing angle with light\n float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0, 1);\n vec2 cascadeAttenuations = vec2(1.0, 1.0);\n cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[0], oneMinusNdotL);\n if (cascadeMix > 0.0 && cascadeIndices.y < getShadowCascadeCount()) {\n cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[1], oneMinusNdotL);\n }\n float attenuation = mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);\n // Falloff to max distance\n return mix(1.0, attenuation, evalShadowFalloff(viewDepth));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n\n\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\n\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\n\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\n\n\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\n\n\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n vec4 viewPos = vec4(frag.position.xyz, 1.0);\n vec4 worldPos = getViewInverse() * viewPos;\n Light shadowLight = getKeyLight();\n vec3 worldLightDirection = getLightDirection(shadowLight);\n float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal);\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "eKhbZNIqwNLpthQKQUjZSg==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "eXnWX1gX5SpBEzZA1SEWsw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/3/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n" + }, + "fHAYL5kFcZV9YTBxlTKatw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/3/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n _fragColor = vec4(albedo * isUnlitEnabled(), opacity);\n}\n\n\n" + }, + "gGKhR05vzJLx7EjPR9F1tA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n // and the texture coordinates\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\nlayout(location = 5) in vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n\n packDeferredFragmentLightmap(\n normalize(_normalWS), \n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*metallicTex, // no use of */getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n" + }, + "grRVm4UWiHKN4KkQrURvQA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTextureMirroredX.frag\n//\n// Draw texture 0 fetched at (1.0 - texcoord.x, texcoord.y)\n//\n// Created by Sam Gondelman on 10/24/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));\n}\n\n\n" + }, + "hBKI+uiq2k/kRg0/lQeo3g==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_shadow_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionWS;\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFadeClip(fadeParams, _positionWS.xyz);\n\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "huZ58zhKPN7/losUzJUE3A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTexture.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n" + }, + "i8tBs+bcbYh7HTWMDox53A==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "iBB5qMCPEJ9z18yrXsFeug==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// subsurfaceScattering_makeProfile.frag\n//\n// Created by Sam Gateau on 6/27/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nfloat gaussian(float v, float r) {\n const float _PI = 3.14159265358979523846;\n return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));\n}\n\nvec3 scatter(float r) {\n // r is the distance expressed in millimeter\n // returns the scatter reflectance\n // Values from GPU Gems 3 \"Advanced Skin Rendering\".\n // Originally taken from real life samples.\n const vec4 profile[6] = vec4[6](\n vec4(0.0064, 0.233, 0.455, 0.649),\n vec4(0.0484, 0.100, 0.336, 0.344),\n vec4(0.1870, 0.118, 0.198, 0.000),\n vec4(0.5670, 0.113, 0.007, 0.007),\n vec4(1.9900, 0.358, 0.004, 0.000),\n vec4(7.4100, 0.078, 0.000, 0.000)\n );\n const int profileNum = 6;\n\n vec3 ret = vec3(0.0);\n for (int i = 0; i < profileNum; i++) {\n float v = profile[i].x * 1.414;\n float g = gaussian(v, r);\n ret += g * profile[i].yzw;\n }\n\n return ret;\n}\n\n\n\nvec3 generateProfile(vec2 uv) {\n return scatter(uv.x * 2.0);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = vec4(generateProfile(varTexCoord0.xy), 1.0);\n}\n\n\n" + }, + "iNjIRgAkEKJSdds4Zoo9Bg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_makeCurvature.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nstruct SurfaceGeometryParams {\n // Resolution info\n vec4 resolutionInfo;\n // Curvature algorithm\n vec4 curvatureInfo;\n};\n\nuniform surfaceGeometryParamsBuffer {\n SurfaceGeometryParams params;\n};\n\nfloat getCurvatureDepthThreshold() {\n return params.curvatureInfo.x;\n}\n\nfloat getCurvatureBasisScale() {\n return params.curvatureInfo.y;\n}\n\nfloat getCurvatureScale() {\n return params.curvatureInfo.w;\n}\n\nbool isFullResolution() {\n return params.resolutionInfo.w == 0.0;\n}\n\n\nuniform sampler2D linearDepthMap;\nfloat getZEye(ivec2 pixel) {\n return -texelFetch(linearDepthMap, pixel, 0).x;\n}\nfloat getZEyeLinear(vec2 texcoord) {\n return -texture(linearDepthMap, texcoord).x;\n}\n\nvec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) {\n return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y);\n}\n\nuniform sampler2D normalMap;\n\nvec3 getRawNormal(vec2 texcoord) {\n return texture(normalMap, texcoord).xyz;\n}\n\nvec3 getWorldNormal(vec2 texcoord) {\n vec3 rawNormal = getRawNormal(texcoord);\n if (isFullResolution()) {\n return unpackNormal(rawNormal);\n } else {\n return normalize((rawNormal - vec3(0.5)) * 2.0);\n }\n}\n\nvec3 getWorldNormalDiff(vec2 texcoord, vec2 delta) {\n return getWorldNormal(texcoord + delta) - getWorldNormal(texcoord - delta);\n}\n\nfloat getEyeDepthDiff(vec2 texcoord, vec2 delta) {\n return getZEyeLinear(texcoord + delta) - getZEyeLinear(texcoord - delta);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n vec2 stereoSideClip = vec2(stereoSide.x, (isStereo() ? 0.5 : 1.0));\n\n // Texcoord to fetch in the deferred texture are the exact UVs comming from vertex shader\n // sideToFrameTexcoord(stereoSideClip, texcoordPos);\n vec2 frameTexcoordPos = varTexCoord0;\n\n // Fetch the z under the pixel (stereo or not)\n float Zeye = getZEye(framePixelPos);\n if (Zeye <= -getPosLinearDepthFar()) {\n outFragColor = vec4(1.0, 0.0, 0.0, 0.0);\n return;\n }\n\n float nearPlaneScale = 0.5 * getProjectionNear();\n\n vec3 worldNormal = getWorldNormal(frameTexcoordPos);\n\n // The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos);\n // vec3 worldPos = (frameTransform._viewInverse * vec4(eyePos, 1.0)).xyz;\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(10.0 * eyePos.xyz), 1.0);\n }*/\n // return;\n\n // Calculate the perspective scale.\n // Clamp to 0.5\n // float perspectiveScale = max(0.5, (-getProjScaleEye() / Zeye));\n float perspectiveScale = max(0.5, (-getCurvatureBasisScale() * getProjectionNear() / Zeye));\n\n // Calculate dF/du and dF/dv\n vec2 viewportScale = perspectiveScale * getInvWidthHeight();\n vec2 du = vec2( viewportScale.x * (float(stereoSide.w) > 0.0 ? 0.5 : 1.0), 0.0f );\n vec2 dv = vec2( 0.0f, viewportScale.y );\n\n vec4 dFdu = vec4(getWorldNormalDiff(frameTexcoordPos, du), getEyeDepthDiff(frameTexcoordPos, du));\n vec4 dFdv = vec4(getWorldNormalDiff(frameTexcoordPos, dv), getEyeDepthDiff(frameTexcoordPos, dv));\n\n float threshold = getCurvatureDepthThreshold();\n dFdu *= step(abs(dFdu.w), threshold);\n dFdv *= step(abs(dFdv.w), threshold); \n\n // Calculate ( du/dx, du/dy, du/dz ) and ( dv/dx, dv/dy, dv/dz )\n // Eval px, py, pz world positions of the basis centered on the world pos of the fragment\n float axeLength = nearPlaneScale;\n\n vec3 ax = (frameTransform._view[0].xyz * axeLength);\n vec3 ay = (frameTransform._view[1].xyz * axeLength);\n\n\n vec3 az = (frameTransform._view[2].xyz * axeLength);\n\n vec4 px = vec4(eyePos + ax, 0.0);\n vec4 py = vec4(eyePos + ay, 0.0);\n vec4 pz = vec4(eyePos + az, 0.0);\n\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(px.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(eyePos.xyz), 1.0);\n }*/\n // return;\n\n\n /* IN case the axis end point goes behind mid way near plane, this shouldn't happen\n if (px.z >= -nearPlaneScale) {\n outFragColor = vec4(1.0, 0.0, 0.0, 1.0);\n return;\n } else if (py.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 1.0, 0.0, 1.0);\n return;\n } else if (pz.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 0.0, 1.0, 1.0);\n return;\n }*/\n \n\n // Project px, py pz to homogeneous clip space\n // mat4 viewProj = getProjection(stereoSide.x);\n mat4 viewProj = getProjectionMono();\n px = viewProj * px;\n py = viewProj * py;\n pz = viewProj * pz;\n\n\n // then to normalized clip space\n px.xy /= px.w;\n py.xy /= py.w;\n pz.xy /= pz.w;\n\n vec2 nclipPos = (texcoordPos - 0.5) * 2.0;\n\n\n //vec4 clipPos = frameTransform._projection[stereoSide.x] * vec4(eyePos, 1.0);\n vec4 clipPos = getProjectionMono() * vec4(eyePos, 1.0);\n nclipPos = clipPos.xy / clipPos.w;\n\n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (nclipPos)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (clipPos.xy / clipPos.w)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n //return;\n\n\n float pixPerspectiveScaleInv = 1.0 / (perspectiveScale);\n px.xy = (px.xy - nclipPos) * pixPerspectiveScaleInv;\n py.xy = (py.xy - nclipPos) * pixPerspectiveScaleInv;\n pz.xy = (pz.xy - nclipPos) * pixPerspectiveScaleInv;\n \n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (px.xy)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (py.xy)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n // return;\n\n // Calculate dF/dx, dF/dy and dF/dz using chain rule\n vec4 dFdx = dFdu * px.x + dFdv * px.y;\n vec4 dFdy = dFdu * py.x + dFdv * py.y;\n vec4 dFdz = dFdu * pz.x + dFdv * pz.y;\n\n vec3 trace = vec3(dFdx.x, dFdy.y, dFdz.z);\n\n /*if (dot(trace, trace) > params.curvatureInfo.w) {\n outFragColor = vec4(dFdx.x, dFdy.y, dFdz.z, 1.0);\n return;\n }*/\n\n // Calculate the mean curvature\n float meanCurvature = ((trace.x + trace.y + trace.z) * 0.33333333333333333) * params.curvatureInfo.w;\n\n outFragColor = vec4(vec3(worldNormal + 1.0) * 0.5, (meanCurvature + 1.0) * 0.5);\n}\n\n\n" + }, + "iSWjcjtbOXRq+yE3M7ZmLw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "iVdwQ2dEvB1gkV0p4/adjA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// overlay3D.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nout vec3 _color;\nout float _alpha;\nout vec2 _texCoord0;\nout vec4 _positionES;\nout vec3 _normalWS;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n _texCoord0 = inTexCoord0.st;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// overlay3D_translucent_unlit.frag\n// fragment shader\n//\n// Created by Zach Pomerantz on 2/2/2016.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform sampler2D originalTexture;\n\nin vec2 _texCoord0;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec4 albedo = texture(originalTexture, _texCoord0);\n\n _fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha);\n}\n\n\n" + }, + "jWfLQBP3hY4gUntsrqpSdw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "kVm0Zs3mBDfls8rIqIm6AQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "kdIMKfBQhKmG8XQB+bWcRw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTransformUnitQuad.vert\n// \n// Draw and transform the unit quad [-1,-1 -> 1,1]\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * pos);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTexture.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, varTexCoord0);\n}\n\n\n" + }, + "kw1zhSuYtq0S+c7hnfMD5Q==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured.frag\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n}\n\n" + }, + "kzz1QfdnZMN4le5dkFTrVw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n\n\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n\n\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive+fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "moNEFfK86uWpWgQ6q6nsxA==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _tangentWS;\nlayout(location = 6) out vec3 _color;\nlayout(location = 7) out float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "mtYx5P+wGdOJ+2MGHppNNw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_shadow.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToClipPos\n { // transformModelToMonoClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n }\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// skin_model_shadow.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 3/24/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n // pass-through to set z-buffer\n _fragColor = vec4(1.0, 1.0, 1.0, 0.0);\n}\n\n\n" + }, + "mwO+fp+K7wX+h3KlIzUQEw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n// model_translucent_fade.frag\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n\n\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\n\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n fragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "npKcxyZ3Zyj+Ys2SB7hVkQ==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_unlit.frag\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _color;\nin vec2 _texCoord0;\n\nlayout(location = 0) out vec4 _fragColor0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0.st);\n float colorAlpha = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n colorAlpha = -_color.a;\n }\n _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a);\n}\n\n" + }, + "oe9F/0BImUlZtf8jGG3qng==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 04/24/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec4 _positionWS;\nlayout(location = 2) out vec2 _texCoord0;\nlayout(location = 3) out vec2 _texCoord1;\nlayout(location = 4) out vec3 _normalWS;\nlayout(location = 5) out vec3 _tangentWS;\nlayout(location = 6) out vec3 _color;\nlayout(location = 7) out float _alpha;\n\nvoid main(void) {\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec4 _positionWS;\nlayout(location = 2) in vec2 _texCoord0;\nlayout(location = 3) in vec2 _texCoord1;\nlayout(location = 4) in vec3 _normalWS;\nlayout(location = 5) in vec3 _tangentWS;\nlayout(location = 6) in vec3 _color;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n\n packDeferredFragment(\n normalize(fragNormalWS.xyz),\n opacity,\n albedo,\n roughness,\n metallic,\n emissive + fadeEmissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "opM7PUkZqQ+y3QE9UPUYHQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_specular_map.frag\n// fragment shader\n//\n// Created by Andrzej Kapolka on 5/6/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#define scatteringMap 6\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\nuniform sampler2D scatteringMap;\nfloat fetchScatteringMap(vec2 uv) {\n float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now\n return max(((scattering - 0.1) / 0.9), 0.0);\n return texture(scatteringMap, uv).r; // boolean scattering for now\n}\n#endif\n\n\n\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\nfloat scatteringTex = (((matKey & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(_texCoord0) : 0.0);\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n {\n metallic = (((matKey & METALLIC_MAP_BIT) != 0) ? metallicTex : metallic);\n}\n;\n\n float scattering = getMaterialScattering(mat);\n {\n scattering = (((matKey & SCATTERING_MAP_BIT) != 0) ? scatteringTex : scattering);\n}\n;\n\n packDeferredFragment(\n normalize(_normalWS), \n opacity,\n albedo,\n roughness,\n metallic,\n emissive,\n occlusionTex,\n scattering);\n}\n\n\n" + }, + "pGKo9pqA3ckrezIXHRSQvw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n\n// OpenGLDisplayPlugin_present.frag\n\nuniform sampler2D colorMap;\n\nin vec2 varTexCoord0;\n\nout vec4 outFragColor;\n\nfloat sRGBFloatToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n\n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 colorToLinearRGB(vec3 srgb) {\n return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));\n}\n\nvoid main(void) {\n outFragColor.a = 1.0;\n outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb);\n}\n\n" + }, + "pUyFVWTgBDMZyiFHN0OcYQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n\n\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\n\n\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\nlayout(location = 6) in vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\n\n\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n" + }, + "q56Rx+BT+YM9MtyICJJVNw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\nlayout(location = 6) out vec4 _positionWS;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n\n\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\n\n\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\nlayout(location = 6) in vec4 _positionWS;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\n\n\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal+fadeEmissive);\n}\n\n\n" + }, + "rDZmLC0T5LVQlr2FMlW/7w==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 9/15/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured.frag\n// fragment shader\n//\n// Created by Sam Gateau on 4/3/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// the albedo texture\nuniform sampler2D originalTexture;\n\n// the interpolated normal\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\n\nvoid main(void) {\n vec4 texel = texture(originalTexture, _texCoord0);\n float colorAlpha = _color.a * texel.a;\n\n packDeferredFragmentTranslucent(\n normalize(_normalWS),\n colorAlpha,\n _color.rgb * texel.rgb,\n DEFAULT_FRESNEL,\n DEFAULT_ROUGHNESS);\n}\n\n" + }, + "rxy49RtNS4dbekgpf/md8Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// fxaa_blend.frag\n// fragment shader\n//\n// Created by Raffi Bedikian on 8/30/15\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nuniform sampler2D colorTexture;\nuniform float sharpenIntensity;\n\nvoid main(void) {\n vec4 pixels[9];\n vec4 sharpenedPixel;\n pixels[0] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,-1), 0);\n pixels[1] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,-1), 0);\n pixels[2] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,-1), 0);\n\n pixels[3] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,0), 0);\n pixels[4] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), 0);\n pixels[5] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,0), 0);\n\n pixels[6] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(-1,1), 0);\n\n\n pixels[7] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0);\n pixels[8] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,1), 0);\n\n sharpenedPixel = pixels[4]*6.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;\n\n\tvec4 minColor = max(vec4(0), pixels[4]-vec4(0.5));\n\tvec4 maxColor = pixels[4]+vec4(0.5);\n outFragColor = clamp(pixels[4] + sharpenedPixel * sharpenIntensity, minColor, maxColor);\n}\n\n\n" + }, + "s1ItJHSP+xyfrbr0ZJMD2Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// surfaceGeometry_makeCurvature.frag\n//\n// Created by Sam Gateau on 6/3/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\nstruct SurfaceGeometryParams {\n // Resolution info\n vec4 resolutionInfo;\n // Curvature algorithm\n vec4 curvatureInfo;\n};\n\nuniform surfaceGeometryParamsBuffer {\n SurfaceGeometryParams params;\n};\n\nfloat getCurvatureDepthThreshold() {\n return params.curvatureInfo.x;\n}\n\nfloat getCurvatureBasisScale() {\n return params.curvatureInfo.y;\n}\n\nfloat getCurvatureScale() {\n return params.curvatureInfo.w;\n}\n\nbool isFullResolution() {\n return params.resolutionInfo.w == 0.0;\n}\n\n\nuniform sampler2D linearDepthMap;\nfloat getZEye(ivec2 pixel) {\n return -texelFetch(linearDepthMap, pixel, 0).x;\n}\nfloat getZEyeLinear(vec2 texcoord) {\n return -texture(linearDepthMap, texcoord).x;\n}\n\nvec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) {\n return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y);\n}\n\nuniform sampler2D normalMap;\n\nvec3 getRawNormal(vec2 texcoord) {\n return texture(normalMap, texcoord).xyz;\n}\n\nvec3 getWorldNormal(vec2 texcoord) {\n vec3 rawNormal = getRawNormal(texcoord);\n if (isFullResolution()) {\n return unpackNormal(rawNormal);\n } else {\n return normalize((rawNormal - vec3(0.5)) * 2.0);\n }\n}\n\nvec3 getWorldNormalDiff(vec2 texcoord, vec2 delta) {\n return getWorldNormal(texcoord + delta) - getWorldNormal(texcoord - delta);\n}\n\nfloat getEyeDepthDiff(vec2 texcoord, vec2 delta) {\n return getZEyeLinear(texcoord + delta) - getZEyeLinear(texcoord - delta);\n}\n\n\n\nin vec2 varTexCoord0;\nout vec4 outFragColor;\n\nvoid main(void) {\n // Pixel being shaded\n ivec2 pixelPos;\n vec2 texcoordPos;\n ivec4 stereoSide;\n ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);\n vec2 stereoSideClip = vec2(stereoSide.x, (isStereo() ? 0.5 : 1.0));\n\n // Texcoord to fetch in the deferred texture are the exact UVs comming from vertex shader\n // sideToFrameTexcoord(stereoSideClip, texcoordPos);\n vec2 frameTexcoordPos = varTexCoord0;\n\n // Fetch the z under the pixel (stereo or not)\n float Zeye = getZEye(framePixelPos);\n if (Zeye <= -getPosLinearDepthFar()) {\n outFragColor = vec4(1.0, 0.0, 0.0, 0.0);\n return;\n }\n\n float nearPlaneScale = 0.5 * getProjectionNear();\n\n vec3 worldNormal = getWorldNormal(frameTexcoordPos);\n\n // The position of the pixel fragment in Eye space then in world space\n vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos);\n // vec3 worldPos = (frameTransform._viewInverse * vec4(eyePos, 1.0)).xyz;\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(10.0 * eyePos.xyz), 1.0);\n }*/\n // return;\n\n // Calculate the perspective scale.\n // Clamp to 0.5\n // float perspectiveScale = max(0.5, (-getProjScaleEye() / Zeye));\n float perspectiveScale = max(0.5, (-getCurvatureBasisScale() * getProjectionNear() / Zeye));\n\n // Calculate dF/du and dF/dv\n vec2 viewportScale = perspectiveScale * getInvWidthHeight();\n vec2 du = vec2( viewportScale.x * (float(stereoSide.w) > 0.0 ? 0.5 : 1.0), 0.0f );\n vec2 dv = vec2( 0.0f, viewportScale.y );\n\n vec4 dFdu = vec4(getWorldNormalDiff(frameTexcoordPos, du), getEyeDepthDiff(frameTexcoordPos, du));\n vec4 dFdv = vec4(getWorldNormalDiff(frameTexcoordPos, dv), getEyeDepthDiff(frameTexcoordPos, dv));\n\n float threshold = getCurvatureDepthThreshold();\n dFdu *= step(abs(dFdu.w), threshold);\n dFdv *= step(abs(dFdv.w), threshold); \n\n // Calculate ( du/dx, du/dy, du/dz ) and ( dv/dx, dv/dy, dv/dz )\n // Eval px, py, pz world positions of the basis centered on the world pos of the fragment\n float axeLength = nearPlaneScale;\n\n vec3 ax = (frameTransform._view[0].xyz * axeLength);\n vec3 ay = (frameTransform._view[1].xyz * axeLength);\n\n\n vec3 az = (frameTransform._view[2].xyz * axeLength);\n\n vec4 px = vec4(eyePos + ax, 0.0);\n vec4 py = vec4(eyePos + ay, 0.0);\n vec4 pz = vec4(eyePos + az, 0.0);\n\n\n /* if (texcoordPos.y > 0.5) {\n outFragColor = vec4(fract(px.xyz), 1.0);\n } else {\n outFragColor = vec4(fract(eyePos.xyz), 1.0);\n }*/\n // return;\n\n\n /* IN case the axis end point goes behind mid way near plane, this shouldn't happen\n if (px.z >= -nearPlaneScale) {\n outFragColor = vec4(1.0, 0.0, 0.0, 1.0);\n return;\n } else if (py.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 1.0, 0.0, 1.0);\n return;\n } else if (pz.z >= -nearPlaneScale) {\n outFragColor = vec4(0.0, 0.0, 1.0, 1.0);\n return;\n }*/\n \n\n // Project px, py pz to homogeneous clip space\n // mat4 viewProj = getProjection(stereoSide.x);\n mat4 viewProj = getProjectionMono();\n px = viewProj * px;\n py = viewProj * py;\n pz = viewProj * pz;\n\n\n // then to normalized clip space\n px.xy /= px.w;\n py.xy /= py.w;\n pz.xy /= pz.w;\n\n vec2 nclipPos = (texcoordPos - 0.5) * 2.0;\n\n\n //vec4 clipPos = frameTransform._projection[stereoSide.x] * vec4(eyePos, 1.0);\n vec4 clipPos = getProjectionMono() * vec4(eyePos, 1.0);\n nclipPos = clipPos.xy / clipPos.w;\n\n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (nclipPos)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (clipPos.xy / clipPos.w)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n //return;\n\n\n float pixPerspectiveScaleInv = 1.0 / (perspectiveScale);\n px.xy = (px.xy - nclipPos) * pixPerspectiveScaleInv;\n py.xy = (py.xy - nclipPos) * pixPerspectiveScaleInv;\n pz.xy = (pz.xy - nclipPos) * pixPerspectiveScaleInv;\n \n /* if (texcoordPos.y > 0.5) {\n // outFragColor = vec4(fract(10.0 * worldPos.xyz), 1.0);\n outFragColor = vec4(fract(10.0 * (px.xy)), 0.0, 1.0);\n\n } else {\n outFragColor = vec4(fract(10.0 * (py.xy)), 0.0, 1.0);\n // outFragColor = vec4(nclipPos * 0.5 + 0.5, 0.0, 1.0);\n }*/\n // return;\n\n // Calculate dF/dx, dF/dy and dF/dz using chain rule\n vec4 dFdx = dFdu * px.x + dFdv * px.y;\n vec4 dFdy = dFdu * py.x + dFdv * py.y;\n vec4 dFdz = dFdu * pz.x + dFdv * pz.y;\n\n vec3 trace = vec3(dFdx.x, dFdy.y, dFdz.z);\n\n /*if (dot(trace, trace) > params.curvatureInfo.w) {\n outFragColor = vec4(dFdx.x, dFdy.y, dFdz.z, 1.0);\n return;\n }*/\n\n // Calculate the mean curvature\n float meanCurvature = ((trace.x + trace.y + trace.z) * 0.33333333333333333) * params.curvatureInfo.w;\n\n outFragColor = vec4(vec3(worldNormal + 1.0) * 0.5, (meanCurvature + 1.0) * 0.5);\n}\n\n\n" + }, + "sB63BIGiJgE/i+mRiEuaXg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// simple_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/04/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\n// Generated on Wed May 23 14:24:07 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nout vec4 _fadeData1;\nout vec4 _fadeData2;\nout vec4 _fadeData3;\n\n\n// the interpolated normal\nout vec3 _normalWS;\nout vec3 _normalMS;\nout vec4 _color;\nout vec2 _texCoord0;\nout vec4 _positionMS;\nout vec4 _positionES;\nout vec4 _positionWS;\n\nvoid main(void) {\n _color = color_sRGBAToLinear(inColor);\n _texCoord0 = inTexCoord0.st;\n _positionMS = inPosition;\n _normalMS = inNormal.xyz;\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n _fadeData1 = inTexCoord2;\n _fadeData2 = inTexCoord3;\n _fadeData3 = inTexCoord4; \n\n}\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// simple_transparent_textured_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 06/05/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n\n\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n\n\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n\n\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n\n\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n// the albedo texture\nuniform sampler2D originalTexture;\n\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec4 _color;\nin vec2 _texCoord0;\nin vec4 _positionWS;\n\n// Declare after all samplers to prevent sampler location mix up with originalTexture\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nin vec4 _fadeData1;\nin vec4 _fadeData2;\nin vec4 _fadeData3;\n\n\n\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = int(_fadeData1.w);\n fadeParams.threshold = _fadeData2.w;\n fadeParams.noiseOffset = _fadeData1.xyz;\n fadeParams.baseOffset = _fadeData2.xyz;\n fadeParams.baseInvSize = _fadeData3.xyz;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n vec4 texel = texture(originalTexture, _texCoord0.st);\n\n\n float opacity = _color.a;\n if (_color.a <= 0.0) {\n texel = color_sRGBAToLinear(texel);\n opacity = -_color.a;\n }\n opacity *= texel.a;\n vec3 albedo = _color.rgb * texel.rgb;\n\n vec3 fragPosition = _positionES.xyz;\n vec3 fragNormal = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n\n _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n 1.0,\n fragPosition,\n fragNormal,\n albedo,\n DEFAULT_FRESNEL,\n 0.0f,\n fadeEmissive,\n DEFAULT_ROUGHNESS,\n opacity),\n opacity);\n\n}\n\n" + }, + "skXS+Y3bVuk+lbr+g/Xsxw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "sqv0FqzLxa9sgQMrrgo86g==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent.vert\n// vertex shader\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "tw56tU7HU9EytMY8/IgFDg==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// deferred_light.vert\n// vertex shader\n//\n// Created by Sam Gateau on 6/16/16.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) out vec2 _texCoord0;\n\nuniform vec4 texcoordFrameTransform;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n _texCoord0 = (pos.xy + 1.0) * 0.5;\n\n _texCoord0 *= texcoordFrameTransform.zw;\n _texCoord0 += texcoordFrameTransform.xy;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// directional_skybox_light.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/8/2015.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\n// the albedo texture\nuniform sampler2D albedoMap;\n\n// the normal texture\nuniform sampler2D normalMap;\n\n// the specular texture\nuniform sampler2D specularMap;\n\n// the depth texture\nuniform sampler2D depthMap;\nuniform sampler2D linearZeyeMap;\n\n// the obscurance texture\nuniform sampler2D obscuranceMap;\n\n// the lighting texture\nuniform sampler2D lightingMap;\n\n\nstruct DeferredFragment {\n vec4 position;\n vec3 normal;\n float metallic;\n vec3 albedo;\n float obscurance;\n vec3 fresnel;\n float roughness;\n int mode;\n float scattering;\n float depthVal;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nDeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n vec4 specularVal;\n \n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n specularVal = texture(specularMap, texcoord);\n frag.obscurance = texture(obscuranceMap, texcoord).x;\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n frag.obscurance = min(specularVal.w, frag.obscurance);\n\n if (frag.mode == FRAG_MODE_SCATTERING) {\n frag.scattering = specularVal.x;\n }\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nDeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) {\n vec4 normalVal;\n vec4 diffuseVal;\n\n DeferredFragment frag;\n frag.depthVal = -1.0;\n normalVal = texture(normalMap, texcoord);\n diffuseVal = texture(albedoMap, texcoord);\n\n // Unpack the normal from the map\n frag.normal = unpackNormal(normalVal.xyz);\n frag.roughness = normalVal.a;\n\n // Diffuse color and unpack the mode and the metallicness\n frag.albedo = diffuseVal.xyz;\n frag.scattering = 0.0;\n unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);\n\n //frag.emissive = specularVal.xyz;\n frag.obscurance = 1.0;\n\n frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz);\n\n return frag;\n}\n\n\nstruct CameraCorrection {\n mat4 _correction;\n mat4 _correctionInverse;\n \n mat4 _prevView;\n mat4 _prevViewInverse;\n};\n \nuniform cameraCorrectionBuffer {\n CameraCorrection cameraCorrection;\n};\n\nstruct DeferredFrameTransform {\n vec4 _pixelInfo;\n vec4 _invPixelInfo;\n vec4 _depthInfo;\n vec4 _stereoInfo;\n mat4 _projection[2];\n mat4 _invProjection[2];\n mat4 _projectionMono;\n mat4 _viewInverse;\n mat4 _view;\n\tmat4 _projectionUnJittered[2];\n\tmat4 _invProjectionUnJittered[2];\n};\n\nuniform deferredFrameTransformBuffer {\n DeferredFrameTransform frameTransform;\n};\n\nvec2 getWidthHeight(int resolutionLevel) {\n return vec2(ivec2(frameTransform._pixelInfo.zw) >> resolutionLevel);\n}\n\nvec2 getInvWidthHeight() {\n return frameTransform._invPixelInfo.xy;\n}\n\nfloat getProjScaleEye() {\n return frameTransform._projection[0][1][1];\n}\n\nfloat getProjScale(int resolutionLevel) {\n return getWidthHeight(resolutionLevel).y * frameTransform._projection[0][1][1] * 0.5;\n}\nmat4 getProjection(int side) {\n return frameTransform._projection[side];\n}\nmat4 getProjectionMono() {\n return frameTransform._projectionMono;\n}\nmat4 getUnjitteredProjection(int side) {\n\treturn frameTransform._projectionUnJittered[side];\n}\nmat4 getUnjitteredInvProjection(int side) {\n\treturn frameTransform._invProjectionUnJittered[side];\n}\n\n// positive near distance of the projection\nfloat getProjectionNear() {\n float planeC = frameTransform._projection[0][2][3] + frameTransform._projection[0][2][2];\n float planeD = frameTransform._projection[0][3][2];\n return planeD / planeC;\n}\n\n// positive far distance of the projection\nfloat getPosLinearDepthFar() {\n return -frameTransform._depthInfo.z;\n}\n\nmat4 getViewInverse() {\n return frameTransform._viewInverse * cameraCorrection._correctionInverse;\n}\n\nmat4 getView() {\n return cameraCorrection._correction * frameTransform._view;\n}\n\nmat4 getPreviousView() {\n return cameraCorrection._prevView;\n}\n\nmat4 getPreviousViewInverse() {\n return cameraCorrection._prevViewInverse;\n}\n\nDeferredFrameTransform getDeferredFrameTransform() {\n DeferredFrameTransform result = frameTransform;\n result._view = getView(); \n result._viewInverse = getViewInverse(); \n return result;\n}\n\nbool isStereo() {\n return frameTransform._stereoInfo.x > 0.0f;\n}\n\nfloat getStereoSideWidth(int resolutionLevel) {\n return float(int(frameTransform._stereoInfo.y) >> resolutionLevel);\n}\nfloat getStereoSideHeight(int resolutionLevel) {\n return float(int(frameTransform._pixelInfo.w) >> resolutionLevel);\n}\n\nvec2 getSideImageSize(int resolutionLevel) {\n return vec2(float(int(frameTransform._stereoInfo.y) >> resolutionLevel), float(int(frameTransform._pixelInfo.w) >> resolutionLevel));\n}\n\nivec4 getStereoSideInfo(int xPos, int resolutionLevel) {\n int sideWidth = int(getStereoSideWidth(resolutionLevel));\n return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo());\n}\n\nfloat evalZeyeFromZdb(float depth) {\n return frameTransform._depthInfo.x / (depth * frameTransform._depthInfo.y + frameTransform._depthInfo.z);\n}\n\nfloat evalZdbFromZeye(float Zeye) {\n return (frameTransform._depthInfo.x - Zeye * frameTransform._depthInfo.z) / (Zeye * frameTransform._depthInfo.y);\n}\n\nvec3 evalEyeNormal(vec3 C) {\n return normalize(cross(dFdx(C), dFdy(C)));\n}\n\nvec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {\n\n\n // compute the view space position using the depth\n vec3 clipPos;\n clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;\n vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);\n return eyePos.xyz / eyePos.w;\n}\n\nvec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {\n\tfloat Zdb = evalZdbFromZeye(Zeye);\n return evalEyePositionFromZdb(side, Zdb, texcoord);\n}\n\nivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) {\n ivec2 fragPos = ivec2(glFragCoord.xy);\n\n stereoSide = getStereoSideInfo(fragPos.x, 0);\n\n pixelPos = fragPos;\n pixelPos.x -= stereoSide.y;\n\n texcoordPos = (vec2(pixelPos) + 0.5) * getInvWidthHeight();\n \n return fragPos;\n}\n\n\n\nvec4 unpackDeferredPosition(float depthValue, vec2 texcoord) {\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n\n return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0);\n}\n\n// This method to unpack position is fastesst\nvec4 unpackDeferredPositionFromZdb(vec2 texcoord) {\n float Zdb = texture(depthMap, texcoord).x;\n\treturn unpackDeferredPosition(Zdb, texcoord);\n}\n\nvec4 unpackDeferredPositionFromZeye(vec2 texcoord) {\n float Zeye = -texture(linearZeyeMap, texcoord).x;\n int side = 0;\n if (isStereo()) {\n if (texcoord.x > 0.5) {\n texcoord.x -= 0.5;\n side = 1;\n }\n texcoord.x *= 2.0;\n }\n return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0);\n}\n\nDeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) {\n\n float depthValue = texture(depthMap, texcoord).r;\n\n DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);\n\n frag.depthVal = depthValue;\n frag.position = unpackDeferredPosition(frag.depthVal, texcoord);\n\n return frag;\n}\n\n\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n\n\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n\n\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {\n Light light = getKeyLight();\n LightAmbient ambient = getLightAmbient();\n\n\n\n // Catch normals perpendicular to the projection plane, hence the magic number for the threshold\n // It should be just 0, but we have inaccuracy so we overshoot\n const float PERPENDICULAR_THRESHOLD = -0.005;\n vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace\n float diffuseDot = dot(fragNormal, -getLightDirection(light));\n float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); \n\n // Reevaluate the shadow attenuation for light facing fragments\n float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;\n\n // Diffuse light is the lightmap dimmed by shadow\n vec3 diffuseLight = lightAttenuation * lightmap;\n\n // Ambient light is the lightmap when in shadow\n vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);\n\n return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nfloat curvatureAO(in float k) {\n return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;\n}\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nif (scattering * isScatteringEnabled() > 0.0) {\n float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;\n float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;\n ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);\n\n obscurance = min(obscurance, ambientOcclusion);\n\n // Diffuse from ambient\n diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;\n\n // Scattering ambient specular is the same as non scattering for now\n // TODO: we should use the same specular answer as for direct lighting\n }\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\n// the curvature texture\nuniform sampler2D curvatureMap;\n\nvec4 fetchCurvature(vec2 texcoord) {\n return texture(curvatureMap, texcoord);\n}\n\n// the curvature texture\nuniform sampler2D diffusedCurvatureMap;\n\nvec4 fetchDiffusedCurvature(vec2 texcoord) {\n return texture(diffusedCurvatureMap, texcoord);\n}\n\nvoid unpackMidLowNormalCurvature(vec2 texcoord, out vec4 midNormalCurvature, out vec4 lowNormalCurvature) {\n midNormalCurvature = fetchCurvature(texcoord);\n lowNormalCurvature = fetchDiffusedCurvature(texcoord);\n midNormalCurvature.xyz = normalize((midNormalCurvature.xyz - 0.5f) * 2.0f);\n lowNormalCurvature.xyz = normalize((lowNormalCurvature.xyz - 0.5f) * 2.0f);\n midNormalCurvature.w = (midNormalCurvature.w * 2.0 - 1.0);\n lowNormalCurvature.w = (lowNormalCurvature.w * 2.0 - 1.0);\n}\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n,scattering, midNormalCurvature, lowNormalCurvature \n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\nlayout(location = 0) in vec2 _texCoord0;\nlayout(location = 0) out vec4 _fragColor;\n\nvoid main(void) {\n DeferredFrameTransform deferredTransform = getDeferredFrameTransform();\n DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);\n\n float shadowAttenuation = 1.0;\n\n // Light mapped or not ?\n if (frag.mode == FRAG_MODE_UNLIT) {\n discard;\n } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {\n discard;\n } else {\n vec4 midNormalCurvature = vec4(0);\n vec4 lowNormalCurvature = vec4(0);\n if (frag.mode == FRAG_MODE_SCATTERING) {\n unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature);\n }\n vec3 color = evalSkyboxGlobalColor(\n getViewInverse(),\n shadowAttenuation,\n frag.obscurance,\n frag.position.xyz,\n frag.normal,\n frag.albedo,\n frag.fresnel,\n frag.metallic,\n frag.roughness,\n frag.scattering,\n midNormalCurvature,\n lowNormalCurvature);\n\n _fragColor = vec4(color, 1.0);\n }\n}\n\n\n" + }, + "txtmQmPsJYbTjZcf2vyAEQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// model_lightmap_normal_map.vert\n// vertex shader\n//\n// Created by Sam Gateau on 11/21/14.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _tangentWS;\nlayout(location = 5) out vec3 _color;\n\nvoid main(void) {\n // pass along the color in linear space\n _color = color_sRGBToLinear(inColor.xyz);\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord1.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_lightmap_normal_map.frag\n// fragment shader\n//\n// Created by Samuel Gateau on 11/19/14.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nvec2 signNotZero(vec2 v) {\n return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);\n}\n\nvec2 float32x3_to_oct(in vec3 v) {\n vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));\n return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p);\n}\n\n\nvec3 oct_to_float32x3(in vec2 e) {\n vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));\n if (v.z < 0.0) {\n v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);\n }\n return normalize(v);\n}\n\nvec3 snorm12x2_to_unorm8x3(vec2 f) {\n vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0));\n float t = floor(u.y / 256.0);\n\n return floor(vec3(\n u.x / 16.0,\n fract(u.x / 16.0) * 256.0 + t,\n u.y - t * 256.0\n )) / 255.0;\n}\n\nvec2 unorm8x3_to_snorm12x2(vec3 u) {\n u *= 255.0;\n u.y *= (1.0 / 16.0);\n vec2 s = vec2( u.x * 16.0 + floor(u.y),\n fract(u.y) * (16.0 * 256.0) + u.z);\n return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0));\n}\n\n\n// Recommended function to pack/unpack vec3 normals to vec3 rgb with best efficiency\nvec3 packNormal(in vec3 n) {\n return snorm12x2_to_unorm8x3(float32x3_to_oct(n));\n}\n\nvec3 unpackNormal(in vec3 p) {\n return oct_to_float32x3(unorm8x3_to_snorm12x2(p));\n}\n\n// Unpack the metallic-mode value\nconst float FRAG_PACK_SHADED_NON_METALLIC = 0.0;\nconst float FRAG_PACK_SHADED_METALLIC = 0.1;\nconst float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);\n\nconst float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;\nconst float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;\nconst float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);\n\nconst float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;\nconst float FRAG_PACK_SCATTERING_METALLIC = 0.5;\nconst float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);\n\nconst float FRAG_PACK_UNLIT = 0.6;\n\nconst int FRAG_MODE_UNLIT = 0;\nconst int FRAG_MODE_SHADED = 1;\nconst int FRAG_MODE_LIGHTMAPPED = 2;\nconst int FRAG_MODE_SCATTERING = 3;\n\nvoid unpackModeMetallic(float rawValue, out int mode, out float metallic) {\n if (rawValue <= FRAG_PACK_SHADED_METALLIC) {\n mode = FRAG_MODE_SHADED;\n metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {\n mode = FRAG_MODE_LIGHTMAPPED;\n metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);\n } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {\n mode = FRAG_MODE_SCATTERING;\n metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);\n } else if (rawValue >= FRAG_PACK_UNLIT) {\n mode = FRAG_MODE_UNLIT;\n metallic = 0.0;\n }\n}\n\nfloat packShadedMetallic(float metallic) {\n return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);\n}\n\nfloat packLightmappedMetallic(float metallic) {\n return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);\n}\n\nfloat packScatteringMetallic(float metallic) {\n return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);\n}\n\nfloat packUnlit() {\n return FRAG_PACK_UNLIT;\n}\n\nlayout(location = 0) out vec4 _fragColor0; // albedo / metallic\nlayout(location = 1) out vec4 _fragColor1; // Normal\nlayout(location = 2) out vec4 _fragColor2; // scattering / emissive / occlusion\nlayout(location = 3) out vec4 _fragColor3; // emissive\n\n// the alpha threshold\nconst float alphaThreshold = 0.5;\nfloat evalOpaqueFinalAlpha(float alpha, float mapAlpha) {\n return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));\n}\n\nconst float DEFAULT_ROUGHNESS = 0.9;\nconst float DEFAULT_SHININESS = 10.0;\nconst float DEFAULT_METALLIC = 0.0;\nconst vec3 DEFAULT_SPECULAR = vec3(0.1);\nconst vec3 DEFAULT_EMISSIVE = vec3(0.0);\nconst float DEFAULT_OCCLUSION = 1.0;\nconst float DEFAULT_SCATTERING = 0.0;\nconst vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n\n\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nvoid packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion);\n \n _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);\n}\n\nvoid packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {\n if (alpha != 1.0) {\n discard;\n }\n\n _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);\n\n _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);\n}\n\nvoid packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {\n if (alpha != 1.0) {\n discard;\n }\n _fragColor0 = vec4(color, packUnlit());\n _fragColor1 = vec4(packNormal(normal), 1.0);\n // _fragColor2 = vec4(vec3(0.0), 1.0);\n _fragColor3 = vec4(color, 1.0);\n}\n\nvoid packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {\n if (alpha <= 0.0) {\n discard;\n }\n _fragColor0 = vec4(albedo.rgb, alpha);\n _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));\n\n}\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\n\n\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define metallicMap 2\nfloat fetchMetallicMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, metallicMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D metallicMap;\nfloat fetchMetallicMap(vec2 uv) {\n return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\n#endif\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nuniform sampler2D emissiveMap;\nvec3 fetchLightmapMap(vec2 uv) {\n vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;\n return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);\n}\n\n\nlayout(location = 0) in vec4 _positionES;\nlayout(location = 1) in vec2 _texCoord0;\nlayout(location = 2) in vec2 _texCoord1;\nlayout(location = 3) in vec3 _normalWS;\nlayout(location = 4) in vec3 _tangentWS;\nlayout(location = 5) in vec3 _color;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedo = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTexel = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nfloat metallicTex = (((matKey & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(_texCoord0) : 0.0);\n\n vec3 lightmapVal = fetchLightmapMap(_texCoord1);\n\n \n vec3 fragNormal;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTexel, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormal = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n packDeferredFragmentLightmap(\n normalize(fragNormal.xyz),\n evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),\n getMaterialAlbedo(mat) * albedo.rgb * _color,\n getMaterialRoughness(mat) * roughness,\n getMaterialMetallic(mat) * metallicTex,\n /*specular, // no use of */ getMaterialFresnel(mat),\n lightmapVal);\n}\n\n\n" + }, + "uZjU4+8nGkPppTDnLze/gw==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\n// USE_DUAL_QUATERNION_SKINNING\n\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n newPosition += clusterMatrix * inPosition * clusterWeight;\n newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;\n newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;\n }\n\n skinnedPosition = newPosition;\n skinnedNormal = newNormal.xyz;\n skinnedTangent = newTangent.xyz;\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n\n\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "vRcMPJHQ7pdP5HfffszNJQ==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent_normal_map.vert\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent_normal_map.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/2018.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "wuZKEFC3qeBD4vDjucv25A==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawUnitQuadTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.\n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const float depth = 1.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n varTexCoord0 = (pos.xy + 1.0) * 0.5;\n\n gl_Position = pos;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawTextureMirroredX.frag\n//\n// Draw texture 0 fetched at (1.0 - texcoord.x, texcoord.y)\n//\n// Created by Sam Gondelman on 10/24/2017\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\nuniform sampler2D colorMap;\n\nlayout(location = 0) in vec2 varTexCoord0;\nlayout(location = 0) out vec4 outFragColor;\n\nvoid main(void) {\n outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));\n}\n\n\n" + }, + "x/Dv0V4xUH2S3fNeKBiX4Q==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:33 2018\n//\n// DrawViewportQuatTransformTexcoord.vert\n//\n// Draw the unit quad [-1,-1 -> 1,1] filling in \n// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec2 varTexCoord0;\n\nvoid main(void) {\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, 0.0, 1.0),\n vec4(1.0, -1.0, 0.0, 1.0),\n vec4(-1.0, 1.0, 0.0, 1.0),\n vec4(1.0, 1.0, 0.0, 1.0)\n );\n vec4 pos = UNIT_QUAD[gl_VertexID];\n\n // standard transform but applied to the Texcoord\n vec4 tc = vec4((pos.xy + 1.0) * 0.5, pos.zw);\n\n TransformObject obj = getTransformObject();\n { // transformModelToWorldPos\n tc = (obj._model * tc);\n }\n\n\n gl_Position = pos;\n varTexCoord0 = tc.xy;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Sat Oct 24 09:34:37 2015\n//\n// toneMapping.frag\n//\n// Draw texture 0 fetched at texcoord.xy\n//\n// Created by Sam Gateau on 6/22/2015\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nstruct ToneMappingParams {\n vec4 _exp_2powExp_s0_s1;\n ivec4 _toneCurve_s0_s1_s2;\n};\n\nconst float INV_GAMMA_22 = 1.0 / 2.2;\nconst int ToneCurveNone = 0;\nconst int ToneCurveGamma22 = 1;\nconst int ToneCurveReinhard = 2;\nconst int ToneCurveFilmic = 3;\n\nuniform toneMappingParamsBuffer {\n ToneMappingParams params;\n};\nfloat getTwoPowExposure() {\n return params._exp_2powExp_s0_s1.y;\n}\nint getToneCurve() {\n return params._toneCurve_s0_s1_s2.x;\n}\n\nuniform sampler2D colorMap;\n \nin vec2 varTexCoord0;\nout vec4 outFragColor;\n \nvoid main(void) {\n vec4 fragColorRaw = texture(colorMap, varTexCoord0);\n vec3 fragColor = fragColorRaw.xyz;\n\n vec3 srcColor = fragColor * getTwoPowExposure();\n\n int toneCurve = getToneCurve();\n vec3 tonedColor = srcColor;\n if (toneCurve == ToneCurveFilmic) {\n vec3 x = max(vec3(0.0), srcColor-0.004);\n tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);\n } else if (toneCurve == ToneCurveReinhard) {\n tonedColor = srcColor/(1.0 + srcColor);\n tonedColor = pow(tonedColor, vec3(INV_GAMMA_22));\n } else if (toneCurve == ToneCurveGamma22) {\n tonedColor = pow(srcColor, vec3(INV_GAMMA_22));\n } // else None toned = src\n\n outFragColor = vec4(tonedColor, 1.0);\n}\n\n\n" + }, + "xRA/pLZvMcYj8UPQjENMCA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_fade_dq.vert\n// vertex shader\n//\n// Created by Olivier Prat on 06/045/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0);\n\n skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:08 2018\n//\n// model_translucent.frag\n// fragment shader\n//\n// Created by Sam Gateau on 2/15/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:08 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec4 _positionWS;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n\n\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS = normalize(_normalWS);\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "xW3hK5HnwlbTZXmqF/0FjA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/14/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nlayout(location = 0) out vec4 _positionES;\nlayout(location = 1) out vec2 _texCoord0;\nlayout(location = 2) out vec2 _texCoord1;\nlayout(location = 3) out vec3 _normalWS;\nlayout(location = 4) out vec3 _color;\nlayout(location = 5) out float _alpha;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n// overlay3D_model.frag\n// fragment shader\n//\n// Created by Sam Gateau on 6/16/15.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n\n\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,\n vec3 albedo, vec3 fresnel, float metallic, float roughness\n) {\n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normal);\n vec3 fragPositionWS = vec3(invViewMat * vec4(position, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance\n);\n color += ambientDiffuse;\n color += ambientSpecular;\n\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation\n);\n color += directionalDiffuse;\n color += directionalSpecular;\n\n // Attenuate the light if haze effect selected\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {\n color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); \n }\n\n return color;\n}\n\n\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _color;\nin float _alpha;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n Material mat = getMaterial();\n BITFIELD matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\n\n\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = 1.0;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n {\n if (opacity < 1.0) {\n discard;\n }\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n\n vec3 fragPosition = _positionES.xyz;\n\n TransformCamera cam = getTransformCamera();\n\n vec4 color = vec4(evalSkyboxGlobalColor(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPosition,\n normalize(_normalWS),\n albedo,\n fresnel,\n metallic,\n roughness),\n opacity);\n\n // And emissive\n color.rgb += emissive * isEmissiveEnabled();\n\n // Apply standard tone mapping\n _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);\n}\n\n" + }, + "xijoUnFWm96KyrGEE3ZJLw==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:23:38 2018\n// skybox.vert\n// vertex shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nlayout(location = 0) out vec3 _normal;\n\nvoid main(void) {\n const float depth = 0.0;\n const vec4 UNIT_QUAD[4] = vec4[4](\n vec4(-1.0, -1.0, depth, 1.0),\n vec4(1.0, -1.0, depth, 1.0),\n vec4(-1.0, 1.0, depth, 1.0),\n vec4(1.0, 1.0, depth, 1.0)\n );\n vec4 inPosition = UNIT_QUAD[gl_VertexID];\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n vec3 clipDir = vec3(inPosition.xy, 0.0);\n vec3 eyeDir;\n { // transformClipToEyeDir\n eyeDir = vec3(cam._projectionInverse * vec4(clipDir.xyz, 1.0)); // Must be 1.0 here\n }\n\n { // transformEyeToWorldDir\n _normal = vec3(cam._viewInverse * vec4(eyeDir.xyz, 0.0));\n }\n\n \n // Position is supposed to come in clip space\n gl_Position = vec4(inPosition.xy, 0.0, 1.0);\n\n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:23:38 2018\n// skybox.frag\n// fragment shader\n//\n// Created by Sam Gateau on 5/5/2015.\n// Copyright 2015 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nuniform samplerCube cubeMap;\n\nstruct Skybox {\n vec4 color;\n};\n\nuniform skyboxBuffer {\n Skybox skybox;\n};\n\nlayout(location = 0) in vec3 _normal;\nlayout(location = 0) out vec4 _fragColor;\n\n//PROCEDURAL_COMMON_BLOCK\n\n#line 1001\n//PROCEDURAL_BLOCK\n\n#line 2033\nvoid main(void) {\n\n#ifdef PROCEDURAL\n\n vec3 color = getSkyboxColor();\n // Protect from NaNs and negative values\n color = mix(color, vec3(0), isnan(color));\n color = max(color, vec3(0));\n // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline\n color = pow(color, vec3(2.2));\n _fragColor = vec4(color, 0.0);\n\n // FIXME: scribe does not yet scrub out else statements\n return;\n\n#else \n vec3 coord = normalize(_normal);\n vec3 color = skybox.color.rgb;\n\n // blend is only set if there is a cubemap\n if (skybox.color.a > 0.0) {\n color = texture(cubeMap, coord).rgb;\n if (skybox.color.a < 1.0) {\n color *= skybox.color.rgb;\n }\n }\n _fragColor = vec4(color, 0.0);\n\n#endif\n\n}\n\n\n" + }, + "xwz86nTbnLr2xG5WgkSlWA==": { + "source": "// VERSION 1//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n// model_translucent_normal_map.vert\n// vertex shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout float _alpha;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec4 _positionES;\nout vec4 _positionWS;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\n\nvoid main(void) {\n _color = color_sRGBToLinear(inColor.xyz);\n _alpha = inColor.w;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * inPosition);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * inPosition);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _normalWS = vec3(dot(mr0, inNormal.xyz), dot(mr1, inNormal.xyz), dot(mr2, inNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n _tangentWS = vec3(dot(mr0, inTangent.xyz), dot(mr1, inTangent.xyz), dot(mr2, inTangent.xyz));\n }\n\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" + }, + "zZdvMn53wg0/1en00Cwp2Q==": { + "source": "// VERSION 0//-------- vertex\n\n//PC 410 core\n// Generated on Wed May 23 14:24:07 2018\n//\n// skin_model_normal_map_fade_dq.vert\n// vertex shader\n//\n// Created by Andrzej Kapolka on 10/29/13.\n// Copyright 2013 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\nlayout(location = 0) in vec4 inPosition;\nlayout(location = 1) in vec4 inNormal;\nlayout(location = 2) in vec4 inColor;\nlayout(location = 3) in vec4 inTexCoord0;\nlayout(location = 4) in vec4 inTangent;\nlayout(location = 5) in ivec4 inSkinClusterIndex;\nlayout(location = 6) in vec4 inSkinClusterWeight;\nlayout(location = 7) in vec4 inTexCoord1;\nlayout(location = 8) in vec4 inTexCoord2;\nlayout(location = 9) in vec4 inTexCoord3;\nlayout(location = 10) in vec4 inTexCoord4;\n// Linear ====> linear RGB\n// sRGB ======> standard RGB with gamma of 2.2\n// YCoCg =====> Luma (Y) chrominance green (Cg) and chrominance orange (Co)\n// https://software.intel.com/en-us/node/503873\n\nfloat color_scalar_sRGBToLinear(float value) {\n const float SRGB_ELBOW = 0.04045;\n \n return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);\n}\n\nvec3 color_sRGBToLinear(vec3 srgb) {\n return vec3(color_scalar_sRGBToLinear(srgb.r), color_scalar_sRGBToLinear(srgb.g), color_scalar_sRGBToLinear(srgb.b));\n}\n\nvec4 color_sRGBAToLinear(vec4 srgba) {\n return vec4(color_sRGBToLinear(srgba.xyz), srgba.w);\n}\n\nvec3 color_LinearToYCoCg(vec3 rgb) {\n\t// Y = R/4 + G/2 + B/4\n\t// Co = R/2 - B/2\n\t// Cg = -R/4 + G/2 - B/4\n\treturn vec3(\n\t\t\trgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0,\n\t\t\trgb.x/2.0 - rgb.z/2.0,\n\t\t-rgb.x/4.0 + rgb.y/2.0 - rgb.z/4.0\n\t);\n}\n\nvec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {\n\t// R = Y + Co - Cg\n\t// G = Y + Cg\n\t// B = Y - Co - Cg\n\treturn vec3(\n\t\tycocg.x + ycocg.y - ycocg.z,\n\t\tycocg.x + ycocg.z,\n\t\tycocg.x - ycocg.y - ycocg.z\n\t);\n}\n\nvec3 color_YCoCgToLinear(vec3 ycocg) {\n\treturn clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));\n}\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\nstruct TransformObject {\n mat4 _model;\n mat4 _modelInverse;\n};\n\nlayout(location=15) in ivec2 _drawCallInfo;\n\n#if defined(GPU_SSBO_TRANSFORM_OBJECT)\nlayout(std140) buffer transformObjectBuffer {\n TransformObject _object[];\n};\nTransformObject getTransformObject() {\n TransformObject transformObject = _object[_drawCallInfo.x];\n return transformObject;\n}\n#else\nuniform samplerBuffer transformObjectBuffer;\n\nTransformObject getTransformObject() {\n int offset = 8 * _drawCallInfo.x;\n TransformObject object;\n object._model[0] = texelFetch(transformObjectBuffer, offset);\n object._model[1] = texelFetch(transformObjectBuffer, offset + 1);\n object._model[2] = texelFetch(transformObjectBuffer, offset + 2);\n object._model[3] = texelFetch(transformObjectBuffer, offset + 3);\n\n object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4);\n object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5);\n object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6);\n object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7);\n\n return object;\n}\n#endif\n\n\n\n\nconst int MAX_CLUSTERS = 128;\nconst int INDICES_PER_VERTEX = 4;\n\n// func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)\n\n// if not SKINNING_SLH\nlayout(std140) uniform skinClusterBuffer {\n mat4 clusterMatrices[MAX_CLUSTERS];\n};\n\nmat4 dualQuatToMat4(vec4 real, vec4 dual) {\n float twoRealXSq = 2.0 * real.x * real.x;\n float twoRealYSq = 2.0 * real.y * real.y;\n float twoRealZSq = 2.0 * real.z * real.z;\n float twoRealXY = 2.0 * real.x * real.y;\n float twoRealXZ = 2.0 * real.x * real.z;\n float twoRealXW = 2.0 * real.x * real.w;\n float twoRealZW = 2.0 * real.z * real.w;\n float twoRealYZ = 2.0 * real.y * real.z;\n float twoRealYW = 2.0 * real.y * real.w;\n vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,\n twoRealXY + twoRealZW,\n twoRealXZ - twoRealYW,\n 0.0);\n vec4 col1 = vec4(twoRealXY - twoRealZW,\n 1.0 - twoRealXSq - twoRealZSq,\n twoRealYZ + twoRealXW,\n 0.0);\n vec4 col2 = vec4(twoRealXZ + twoRealYW,\n twoRealYZ - twoRealXW,\n 1.0 - twoRealXSq - twoRealYSq,\n 0.0);\n vec4 col3 = vec4(2.0 * (-dual.w * real.x + dual.x * real.w - dual.y * real.z + dual.z * real.y),\n 2.0 * (-dual.w * real.y + dual.x * real.z + dual.y * real.w - dual.z * real.x),\n 2.0 * (-dual.w * real.z - dual.x * real.y + dual.y * real.x + dual.z * real.w),\n 1.0);\n\n return mat4(col0, col1, col2, col3);\n}\n\n// dual quaternion linear blending\nvoid skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n}\n\nvoid skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,\n out vec4 skinnedPosition, out vec3 skinnedNormal) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n}\n\nvoid skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,\n out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {\n\n // linearly blend scale and dual quaternion components\n vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];\n\n for (int i = 0; i < INDICES_PER_VERTEX; i++) {\n mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];\n float clusterWeight = skinClusterWeight[i];\n\n vec4 scale = clusterMatrix[0];\n vec4 real = clusterMatrix[1];\n vec4 dual = clusterMatrix[2];\n vec4 cauterizedPos = clusterMatrix[3];\n\n // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.\n float dqClusterWeight = clusterWeight;\n if (dot(real, polarityReference) < 0.0) {\n dqClusterWeight = -clusterWeight;\n }\n\n sAccum += scale * clusterWeight;\n rAccum += real * dqClusterWeight;\n dAccum += dual * dqClusterWeight;\n cAccum += cauterizedPos * clusterWeight;\n }\n\n // normalize dual quaternion\n float norm = length(rAccum);\n rAccum /= norm;\n dAccum /= norm;\n\n // conversion from dual quaternion to 4x4 matrix.\n mat4 m = dualQuatToMat4(rAccum, dAccum);\n\n // sAccum.w indicates the amount of cauterization for this vertex.\n // 0 indicates no cauterization and 1 indicates full cauterization.\n // TODO: make this cauterization smoother or implement full dual-quaternion scale support.\n const float CAUTERIZATION_THRESHOLD = 0.1;\n if (sAccum.w > CAUTERIZATION_THRESHOLD) {\n skinnedPosition = cAccum;\n } else {\n sAccum.w = 1.0;\n skinnedPosition = m * (sAccum * inPosition);\n }\n\n skinnedNormal = vec3(m * vec4(inNormal, 0));\n skinnedTangent = vec3(m * vec4(inTangent, 0));\n}\n\n// if USE_DUAL_QUATERNION_SKINNING\n\n\n\nconst int MAX_TEXCOORDS = 2;\n\nstruct TexMapArray { \n// mat4 _texcoordTransforms[MAX_TEXCOORDS];\n mat4 _texcoordTransforms0;\n mat4 _texcoordTransforms1;\n vec4 _lightmapParams;\n};\n\nuniform texMapArrayBuffer {\n TexMapArray _texMapArray;\n};\n\nTexMapArray getTexMapArray() {\n return _texMapArray;\n}\n\n\n\nout vec4 _positionES;\nout vec2 _texCoord0;\nout vec2 _texCoord1;\nout vec3 _normalWS;\nout vec3 _tangentWS;\nout vec3 _color;\nout float _alpha;\nout vec4 _positionWS;\n\nvoid main(void) {\n vec4 position = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0);\n vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0);\n\n skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);\n\n // pass along the color\n _color = color_sRGBToLinear(inColor.rgb);\n _alpha = inColor.a;\n\n TexMapArray texMapArray = getTexMapArray();\n {\n _texCoord0 = (texMapArray._texcoordTransforms0 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n {\n _texCoord1 = (texMapArray._texcoordTransforms1 * vec4(inTexCoord0.st, 0.0, 1.0)).st;\n}\n\n\n interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0);\n interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0);\n\n // standard transform\n TransformCamera cam = getTransformCamera();\n TransformObject obj = getTransformObject();\n { // transformModelToEyeAndClipPos\n vec4 eyeWAPos;\n { // _transformModelToEyeWorldAlignedPos\n highp mat4 _mv = obj._model;\n _mv[3].xyz -= cam._viewInverse[3].xyz;\n highp vec4 _eyeWApos = (_mv * position);\n eyeWAPos = _eyeWApos;\n }\n\n gl_Position = cam._projectionViewUntranslated * eyeWAPos;\n _positionES = vec4((cam._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);\n \n {\n#ifdef GPU_TRANSFORM_IS_STEREO\n\n#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN\n vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));\n vec2 eyeOffsetScale = vec2(-0.5, +0.5);\n uint eyeIndex = uint(_stereoSide);\n gl_ClipDistance[0] = dot(gl_Position, eyeClipEdge[eyeIndex]);\n float newClipPosX = gl_Position.x * 0.5 + eyeOffsetScale[eyeIndex] * gl_Position.w;\n gl_Position.x = newClipPosX;\n#endif\n\n#else\n#endif\n }\n\n }\n\n { // transformModelToWorldPos\n _positionWS = (obj._model * position);\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedNormal.xyz = vec3(dot(mr0, interpolatedNormal.xyz), dot(mr1, interpolatedNormal.xyz), dot(mr2, interpolatedNormal.xyz));\n }\n\n { // transformModelToEyeDir\t\t\n vec3 mr0 = obj._modelInverse[0].xyz;\n vec3 mr1 = obj._modelInverse[1].xyz;\n vec3 mr2 = obj._modelInverse[2].xyz;\n interpolatedTangent.xyz = vec3(dot(mr0, interpolatedTangent.xyz), dot(mr1, interpolatedTangent.xyz), dot(mr2, interpolatedTangent.xyz));\n }\n\n\n _normalWS = interpolatedNormal.xyz;\n _tangentWS = interpolatedTangent.xyz;\n}\n\n\n//-------- pixel\n\n//PC 410 core\n// Generated on Wed May 23 14:24:09 2018\n//\n// model_translucent_normal_map_fade.frag\n// fragment shader\n//\n// Created by Olivier Prat on 23/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// The material values (at least the material key) must be precisely bitwise accurate\n// to what is provided by the uniform buffer, or the material key has the wrong bits\n\nstruct Material {\n vec4 _emissiveOpacity;\n vec4 _albedoRoughness;\n vec4 _fresnelMetallic;\n vec4 _scatteringSpare2Key;\n};\n\nuniform materialBuffer {\n Material _mat;\n};\n\nMaterial getMaterial() {\n return _mat;\n}\n\nvec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }\nfloat getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }\n\nvec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }\nfloat getMaterialRoughness(Material m) { return m._albedoRoughness.a; }\n\nvec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }\nfloat getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }\n\nfloat getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }\n\nfloat getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }\n\nBITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }\n\nconst BITFIELD EMISSIVE_VAL_BIT = 0x00000001;\nconst BITFIELD UNLIT_VAL_BIT = 0x00000002;\nconst BITFIELD ALBEDO_VAL_BIT = 0x00000004;\nconst BITFIELD METALLIC_VAL_BIT = 0x00000008;\nconst BITFIELD GLOSSY_VAL_BIT = 0x00000010;\nconst BITFIELD OPACITY_VAL_BIT = 0x00000020;\nconst BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;\nconst BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;\nconst BITFIELD SCATTERING_VAL_BIT = 0x00000100;\n\n\nconst BITFIELD EMISSIVE_MAP_BIT = 0x00000200;\nconst BITFIELD ALBEDO_MAP_BIT = 0x00000400;\nconst BITFIELD METALLIC_MAP_BIT = 0x00000800;\nconst BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;\nconst BITFIELD NORMAL_MAP_BIT = 0x00002000;\nconst BITFIELD OCCLUSION_MAP_BIT = 0x00004000;\nconst BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;\nconst BITFIELD SCATTERING_MAP_BIT = 0x00010000;\n\n// glsl / C++ compatible source as interface for Light\n#ifndef LightVolume_Shared_slh\n#define LightVolume_Shared_slh\n\n// Light.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightVolumeConstRef LightVolume\n\nstruct LightVolume {\n vec4 positionRadius;\n vec4 directionSpotCos;\n};\n\nbool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }\nbool lightVolume_isSpot(LightVolume lv) { return bool(lv.directionSpotCos.w >= 0.f); }\n\nvec3 lightVolume_getPosition(LightVolume lv) { return lv.positionRadius.xyz; }\nfloat lightVolume_getRadius(LightVolume lv) { return lv.positionRadius.w; }\nfloat lightVolume_getRadiusSquare(LightVolume lv) { return lv.positionRadius.w * lv.positionRadius.w; }\nvec3 lightVolume_getDirection(LightVolume lv) { return lv.directionSpotCos.xyz; } // direction is -Z axis\n\nfloat lightVolume_getSpotAngleCos(LightVolume lv) { return lv.directionSpotCos.w; }\nvec2 lightVolume_getSpotOutsideNormal2(LightVolume lv) { return vec2(-sqrt(1.0 - lv.directionSpotCos.w * lv.directionSpotCos.w), lv.directionSpotCos.w); }\n\n\nbool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2) {\n fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;\n fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);\n\n // Kill if too far from the light center\n return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {\n // Kill if not in the spot light (ah ah !)\n cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);\n return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));\n}\n\nbool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {\n if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {\n return false;\n }\n\n // Allright we re valid in the volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n\n return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);\n}\n\n#endif\n\n\n// // glsl / C++ compatible source as interface for Light\n#ifndef LightIrradiance_Shared_slh\n#define LightIrradiance_Shared_slh\n\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define LightIrradianceConstRef LightIrradiance\n\nstruct LightIrradiance {\n vec4 colorIntensity;\n // falloffRadius, cutoffRadius, falloffSpot, spare\n vec4 attenuation;\n};\n\n\nvec3 lightIrradiance_getColor(LightIrradiance li) { return li.colorIntensity.xyz; }\nfloat lightIrradiance_getIntensity(LightIrradiance li) { return li.colorIntensity.w; }\nvec3 lightIrradiance_getIrradiance(LightIrradiance li) { return li.colorIntensity.xyz * li.colorIntensity.w; }\nfloat lightIrradiance_getFalloffRadius(LightIrradiance li) { return li.attenuation.x; }\nfloat lightIrradiance_getCutoffRadius(LightIrradiance li) { return li.attenuation.y; }\nfloat lightIrradiance_getFalloffSpot(LightIrradiance li) { return li.attenuation.z; }\n\n\n// Light is the light source its self, d is the light's distance calculated as length(unnormalized light vector).\nfloat lightIrradiance_evalLightAttenuation(LightIrradiance li, float d) {\n float radius = lightIrradiance_getFalloffRadius(li);\n float cutoff = lightIrradiance_getCutoffRadius(li);\n float denom = (d / radius) + 1.0;\n float attenuation = 1.0 / (denom * denom);\n\n // \"Fade\" the edges of light sources to make things look a bit more attractive.\n // Note: this tends to look a bit odd at lower exponents.\n attenuation *= min(1.0, max(0.0, -(d - cutoff)));\n\n return attenuation;\n}\n\n\nfloat lightIrradiance_evalLightSpotAttenuation(LightIrradiance li, float cosA) {\n return pow(cosA, lightIrradiance_getFalloffSpot(li));\n}\n\n\n#endif\n\n\n// // NOw lets define Light\nstruct Light {\n LightVolume volume;\n LightIrradiance irradiance;\n};\n\nbool light_isSpot(Light l) { return lightVolume_isSpot(l.volume); }\n\nvec3 getLightPosition(Light l) { return lightVolume_getPosition(l.volume); }\nvec3 getLightDirection(Light l) { return lightVolume_getDirection(l.volume); }\n\nvec3 getLightColor(Light l) { return lightIrradiance_getColor(l.irradiance); }\nfloat getLightIntensity(Light l) { return lightIrradiance_getIntensity(l.irradiance); }\nvec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradiance); }\n\n// Ambient lighting needs extra info provided from a different Buffer\n// glsl / C++ compatible source as interface for Light\n#ifndef SphericalHarmonics_Shared_slh\n#define SphericalHarmonics_Shared_slh\n\n// SphericalHarmonics.shared.slh\n// libraries/graphics/src/graphics\n//\n// Created by Sam Gateau on 14/9/2016.\n// Copyright 2014 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n#define SphericalHarmonicsConstRef SphericalHarmonics\n\nstruct SphericalHarmonics {\n vec4 L00;\n vec4 L1m1;\n vec4 L10;\n vec4 L11;\n vec4 L2m2;\n vec4 L2m1;\n vec4 L20;\n vec4 L21;\n vec4 L22;\n};\n\nvec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {\n\n vec3 dir = direction.xyz;\n\n const float C1 = 0.429043;\n const float C2 = 0.511664;\n const float C3 = 0.743125;\n const float C4 = 0.886227;\n const float C5 = 0.247708;\n\n vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +\n C3 * sh.L20 * dir.z * dir.z +\n C4 * sh.L00 - C5 * sh.L20 +\n 2.0 * C1 * (sh.L2m2 * dir.x * dir.y +\n sh.L21 * dir.x * dir.z +\n sh.L2m1 * dir.y * dir.z) +\n 2.0 * C2 * (sh.L11 * dir.x +\n sh.L1m1 * dir.y +\n sh.L10 * dir.z);\n return value;\n}\n\n#endif\n\n\n// End C++ compatible// Light Ambient\n\nstruct LightAmbient {\n vec4 _ambient;\n SphericalHarmonics _ambientSphere;\n mat4 transform;\n};\n\nSphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }\n\n\nfloat getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }\nbool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }\nfloat getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }\n\nstruct LightingModel {\n vec4 _UnlitEmissiveLightmapBackground;\n vec4 _ScatteringDiffuseSpecularAlbedo;\n vec4 _AmbientDirectionalPointSpot;\n vec4 _ShowContourObscuranceWireframe;\n vec4 _Haze_spareyzw;\n};\n\nuniform lightingModelBuffer{\n LightingModel lightingModel;\n};\n\nfloat isUnlitEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.x;\n}\nfloat isEmissiveEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.y;\n}\nfloat isLightmapEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.z;\n}\nfloat isBackgroundEnabled() {\n return lightingModel._UnlitEmissiveLightmapBackground.w;\n}\nfloat isObscuranceEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.y;\n}\n\nfloat isScatteringEnabled() {\n\n\n return lightingModel._ScatteringDiffuseSpecularAlbedo.x;\n}\nfloat isDiffuseEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.y;\n}\nfloat isSpecularEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.z;\n}\nfloat isAlbedoEnabled() {\n return lightingModel._ScatteringDiffuseSpecularAlbedo.w;\n}\n\nfloat isAmbientEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.x;\n}\nfloat isDirectionalEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.y;\n}\nfloat isPointEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.z;\n}\nfloat isSpotEnabled() {\n return lightingModel._AmbientDirectionalPointSpot.w;\n}\n\nfloat isShowLightContour() {\n return lightingModel._ShowContourObscuranceWireframe.x;\n}\n\nfloat isWireframeEnabled() {\n return lightingModel._ShowContourObscuranceWireframe.z;\n}\n\nfloat isHazeEnabled() {\n return lightingModel._Haze_spareyzw.x;\n}\n\n\n\nstruct SurfaceData {\n vec3 normal;\n vec3 eyeDir;\n vec3 lightDir;\n vec3 halfDir;\n float roughness;\n float roughness2;\n float roughness4;\n float ndotv;\n float ndotl;\n float ndoth;\n float ldoth;\n float smithInvG1NdotV;\n};\n\nvec3 getFresnelF0(float metallic, vec3 metalF0) {\n // Enable continuous metallness value by lerping between dielectric\n // and metal fresnel F0 value based on the \"metallic\" parameter\n return mix(vec3(0.03), metalF0, metallic);\n}\nfloat evalSmithInvG1(float roughness4, float ndotd) {\n return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));\n}\n\nSurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {\n SurfaceData surface;\n surface.eyeDir = eyeDir;\n surface.normal = normal;\n surface.roughness = mix(0.01, 1.0, roughness);\n surface.roughness2 = surface.roughness * surface.roughness;\n surface.roughness4 = surface.roughness2 * surface.roughness2;\n surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);\n surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);\n\n // These values will be set when we know the light direction, in updateSurfaceDataWithLight\n surface.ndoth = 0.0;\n surface.ndotl = 0.0;\n surface.ldoth = 0.0;\n surface.lightDir = vec3(0,0,1);\n surface.halfDir = vec3(0,0,1);\n\n return surface;\n}\n\nvoid updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {\n surface.lightDir = lightDir;\n surface.halfDir = normalize(surface.eyeDir + lightDir);\n vec3 dots;\n dots.x = dot(surface.normal, surface.halfDir);\n dots.y = dot(surface.normal, surface.lightDir);\n dots.z = dot(surface.halfDir, surface.lightDir);\n dots = clamp(dots, vec3(0), vec3(1));\n surface.ndoth = dots.x;\n surface.ndotl = dots.y;\n surface.ldoth = dots.z;\n}\n\nvec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return vec3(exponential) + fresnelColor * (1.0 - exponential);\n}\n\nfloat fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {\n float base = 1.0 - surface.ldoth;\n //float exponential = pow(base, 5.0);\n float base2 = base * base;\n float exponential = base * base2 * base2;\n return (exponential) + fresnelScalar * (1.0 - exponential);\n}\n\nfloat specularDistribution(SurfaceData surface) {\n // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf\n // for details of equations, especially page 20\n float denom = (surface.ndoth*surface.ndoth * (surface.roughness4 - 1.0) + 1.0);\n denom *= denom;\n // Add geometric factors G1(n,l) and G1(n,v)\n float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);\n denom *= surface.smithInvG1NdotV * smithInvG1NdotL;\n // Don't divide by PI as this is part of the light normalization factor\n float power = surface.roughness4 / denom;\n return power;\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\n// Frag Shading returns the diffuse amount as W and the specular rgb as xyz\nvec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n float fresnelScalar = fresnelSchlickScalar(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;\n float diffuse = angleAttenuation * (1.0 - fresnelScalar);\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, diffuse);\n}\n\nvec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {\n // Incident angle attenuation\n float angleAttenuation = surface.ndotl;\n\n // Specular Lighting\n vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);\n float power = specularDistribution(surface);\n vec3 specular = fresnelColor * power * angleAttenuation;\n\n // We don't divided by PI, as the \"normalized\" equations state we should, because we decide, as Naty Hoffman, that\n // we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit\n // by a white light of intensity 1. But this is an arbitrary normalization of what light intensity \"means\".\n // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf\n // page 23 paragraph \"Punctual light sources\")\n return vec4(specular, 0.f);\n}\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\nuniform sampler2D scatteringSpecularBeckmann;\n\nfloat fetchSpecularBeckmann(float ndoth, float roughness) {\n return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);\n}\n\nvec2 skinSpecular(SurfaceData surface, float intensity) {\n vec2 result = vec2(0.0, 1.0);\n if (surface.ndotl > 0.0) {\n float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);\n float F = fresnelSchlickScalar(0.028, surface);\n float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);\n result.x = surface.ndotl * intensity * frSpec;\n result.y -= F;\n }\n\n return result;\n}\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 6/8/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\nuniform sampler2D scatteringLUT;\n\nvec3 fetchBRDF(float LdotN, float curvature) {\n return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;\n}\n\nvec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {\n return vec3(\n fetchBRDF(LdotNSpectrum.r, curvature).r,\n fetchBRDF(LdotNSpectrum.g, curvature).g,\n fetchBRDF(LdotNSpectrum.b, curvature).b);\n}\n\n// Subsurface Scattering parameters\nstruct ScatteringParameters {\n vec4 normalBendInfo; // R, G, B, factor\n vec4 curvatureInfo;// Offset, Scale, level\n vec4 debugFlags;\n};\n\nuniform subsurfaceScatteringParametersBuffer {\n ScatteringParameters parameters;\n};\n\nvec3 getBendFactor() {\n return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;\n}\n\nfloat getScatteringLevel() {\n return parameters.curvatureInfo.z;\n}\n\nbool showBRDF() {\n return parameters.curvatureInfo.w > 0.0;\n}\n\nbool showCurvature() {\n return parameters.debugFlags.x > 0.0;\n}\nbool showDiffusedNormal() {\n return parameters.debugFlags.y > 0.0;\n}\n\n\nfloat tuneCurvatureUnsigned(float curvature) {\n return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;\n}\n\nfloat unpackCurvature(float packedCurvature) {\n return (packedCurvature * 2.0 - 1.0);\n}\n\nvec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {\n vec3 bendFactorSpectrum = getBendFactor();\n // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));\n vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));\n vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));\n vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));\n\n\n\n vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));\n\n return NdotLSpectrum;\n}\n\n\n\n\n\nvec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {\n if (showDiffusedNormal()) {\n return lowNormal * 0.5 + vec3(0.5);\n }\n if (showCurvature()) {\n return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature));\n }\n\n vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);\n\n float tunedCurvature = tuneCurvatureUnsigned(curvature);\n\n vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);\n return brdf;\n}\n\n\n\n\nvoid evalFragShading(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n if (scattering * isScatteringEnabled() > 0.0) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n diffuse = mix(vec3(surface.ndotl), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n } else {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n specular = shading.xyz;\n }\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\n\nvoid evalFragShadingScattering(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,\n float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {\n vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);\n float NdotL = surface.ndotl;\n diffuse = mix(vec3(NdotL), brdf, scattering);\n\n // Specular Lighting\n vec2 specularBrdf = skinSpecular(surface, 1.0);\n \n diffuse *= specularBrdf.y;\n specular = vec3(specularBrdf.x);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n}\n\nvoid evalFragShadingGloss(out vec3 diffuse, out vec3 specular,\n float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {\n vec4 shading = evalPBRShading(metallic, fresnel, surface);\n diffuse = vec3(shading.w);\n diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());\n specular = shading.xyz;\n}\n\n\nuniform keyLightBuffer {\n Light light;\n};\nLight getKeyLight() {\n return light;\n}\n\n\nuniform lightAmbientBuffer {\n LightAmbient lightAmbient;\n};\n\nLightAmbient getLightAmbient() {\n return lightAmbient;\n}\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nconst int HAZE_MODE_IS_ACTIVE = 1 << 0;\nconst int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;\nconst int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;\nconst int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;\nconst int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;\n\nstruct HazeParams {\n vec3 hazeColor;\n float hazeGlareBlend;\n\n vec3 hazeGlareColor;\n float hazeBaseReference;\n\n vec3 colorModulationFactor;\n int hazeMode;\n\n mat4 transform;\n float backgroundBlend;\n\n float hazeRangeFactor;\n float hazeHeightFactor;\n\n float hazeKeyLightRangeFactor;\n float hazeKeyLightAltitudeFactor;\n};\n\nlayout(std140) uniform hazeBuffer {\n HazeParams hazeParams;\n};\n\n\n// Input:\n// color - fragment original color\n// lightDirectionWS - parameters of the keylight\n// fragPositionWS - fragment position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {\n // Directional light attenuation is simulated by assuming the light source is at a fixed height above the\n // fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height\n //\n // The distance is computed from the height and the directional light orientation\n // The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees\n\n // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)\n float height_95p = 2000.0;\n const float log_p_005 = log(0.05);\n if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {\n height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor;\n }\n\n // Note that we need the sine to be positive\n float sin_pitch = abs(lightDirectionWS.y);\n \n float distance;\n const float minimumSinPitch = 0.001;\n if (sin_pitch < minimumSinPitch) {\n distance = height_95p / minimumSinPitch;\n } else {\n distance = height_95p / sin_pitch;\n }\n\n // Integration is from the fragment towards the light source\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeKeyLightRangeFactor * \n exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n // Note that t is constant and equal to -log(0.05)\n // float t = hazeParams.hazeAltitudeFactor * height_95p;\n // hazeIntegral *= (1.0 - exp (-t)) / t;\n hazeIntegral *= 0.3171178;\n\n return color * exp(-hazeIntegral);\n}\n\n// Input:\n// fragColor - fragment original color\n// fragPositionES - fragment position in eye coordinates\n// fragPositionWS - fragment position in world coordinates\n// eyePositionWS - eye position in world coordinates\n// Output:\n// fragment colour after haze effect\n//\n// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission\n//\nvec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {\n // Distance to fragment \n float distance = length(fragPositionES);\n float eyeWorldHeight = eyePositionWS.y;\n\n // Convert haze colour from uniform into a vec4\n vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);\n\n // Use the haze colour for the glare colour, if blend is not enabled\n vec4 blendedHazeColor;\n if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {\n // Directional light component is a function of the angle from the eye, between the fragment and the sun\n vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);\n\n float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));\n float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));\n\n vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);\n\n blendedHazeColor = mix(hazeColor, glareColor, power);\n } else {\n blendedHazeColor = hazeColor;\n }\n\n vec4 potentialFragColor;\n\n if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) {\n // Compute separately for each colour\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n vec3 hazeDensityDistribution = \n hazeParams.colorModulationFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n vec3 hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n\n vec3 hazeAmount = 1.0 - exp(-hazeIntegral);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0));\n } else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) {\n // Haze is based only on range\n float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor);\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n } else {\n // Haze is based on both range and altitude\n // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt\n\n // Note that the haze base reference affects only the haze density as function of altitude\n float hazeDensityDistribution = \n hazeParams.hazeRangeFactor * \n exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));\n\n float hazeIntegral = hazeDensityDistribution * distance;\n\n const float slopeThreshold = 0.01;\n float deltaHeight = fragPositionWS.y - eyeWorldHeight;\n if (abs(deltaHeight) > slopeThreshold) {\n float t = hazeParams.hazeHeightFactor * deltaHeight;\n // Protect from wild values\n const float EPSILON = 0.0000001f;\n if (abs(t) > EPSILON) {\n hazeIntegral *= (1.0 - exp (-t)) / t;\n }\n }\n\n float hazeAmount = 1.0 - exp(-hazeIntegral);\n\n\n\n // Compute color after haze effect\n potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount);\n }\n\n // Mix with background at far range\n const float BLEND_DISTANCE = 27000.0f;\n vec4 outFragColor;\n if (distance > BLEND_DISTANCE) {\n outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);\n } else {\n outFragColor = potentialFragColor;\n }\n\n return outFragColor;\n}\n\nvec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) {\n float f = pow(1.0 - ndotd, 5.0);\n return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;\n}\n\n// declareSkyboxMap\nuniform samplerCube skyboxMap;\n\nvec4 evalSkyboxLight(vec3 direction, float lod) {\n // textureQueryLevels is not available until #430, so we require explicit lod\n // float mipmapLevel = lod * textureQueryLevels(skyboxMap);\n\n#if !defined(GL_ES)\n float filterLod = textureQueryLod(skyboxMap, direction).x;\n // Keep texture filtering LOD as limit to prevent aliasing on specular reflection\n lod = max(lod, filterLod);\n#endif\n\n return textureLod(skyboxMap, direction, lod);\n}\n\nvec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, vec3 lightDir) {\n vec3 specularLight;\n if (getLightHasAmbientMap(ambient))\n {\n float levels = getLightAmbientMapNumMips(ambient);\n float m = 12.0 / (1.0+11.0*surface.roughness);\n float lod = levels - m;\n lod = max(lod, 0.0);\n specularLight = evalSkyboxLight(lightDir, lod).xyz;\n }\n else\n {\n specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;\n }\n return specularLight;\n}\n\n\nvoid evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, \n float metallic, vec3 fresnelF0, vec3 albedo, float obscurance\n) {\n\n // Rotate surface normal and eye direction\n vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;\n vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;\nvec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);\n\n diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * \n sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;\n\n // Specular highlight from ambient\n vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);\n specular = evalAmbientSpecularIrradiance(ambient, surface, ambientSpaceLightDir) * ambientFresnel;\n\nobscurance = mix(1.0, obscurance, isObscuranceEnabled());\n\n float lightEnergy = obscurance * getLightAmbientIntensity(ambient);\n\n diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());\n\n lightEnergy *= isAmbientEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\nvoid evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,\n SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n) {\n\n // Attenuation\n vec3 lightEnergy = shadow * lightIrradiance;\n\n updateSurfaceDataWithLight(surface, -lightDir);\n\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n);\n\n lightEnergy *= isDirectionalEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n}\n\n\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) \n{\n \n // prepareGlobalLight\n // Transform directions to worldspace\n vec3 fragNormalWS = vec3(normalWS);\n vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0));\n vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;\n vec3 fragEyeDirWS = normalize(fragEyeVectorWS);\n\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n\n\n \n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);\n\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);\n color += ambientDiffuse;\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);\n color += directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n fragPositionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector in world coordinates\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\nvec3 evalGlobalLightingAlphaBlendedWithHaze(\n mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, \n vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) \n{\n // Get light\n Light light = getKeyLight();\n LightAmbient lightAmbient = getLightAmbient();\n \n vec3 lightDirection = getLightDirection(light);\n vec3 lightIrradiance = getLightIrradiance(light);\n\n vec3 color = vec3(0.0);\n\n \n color = prevLighting;\n color += emissive * isEmissiveEnabled();\n\n // Ambient\n vec3 ambientDiffuse;\n vec3 ambientSpecular;\n evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);\n\n // Directional\n vec3 directionalDiffuse;\n vec3 directionalSpecular;\n evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);\n\n color += ambientDiffuse + directionalDiffuse;\n color += (ambientSpecular + directionalSpecular) / opacity;\n\n // Haze\n if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {\n vec4 colorV4 = computeHazeColor(\n vec4(color, 1.0), // fragment original color\n positionES, // fragment position in eye coordinates\n positionWS, // fragment position in world coordinates\n invViewMat[3].xyz, // eye position in world coordinates\n lightDirection // keylight direction vector\n );\n\n color = colorV4.rgb;\n }\n\n return color;\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 15/01/18.\n// Copyright 2018 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n// Everything about light\nuniform lightBuffer {\n Light lightArray[256];\n};\nLight getLight(int index) {\n return lightArray[index];\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n \n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n\n lightEnergy *= isPointEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edge\n float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Sam Gateau on 7/5/16.\n// Copyright 2016 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n\n\n\nvoid evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,\n vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,\n float metallic, vec3 fresnel, vec3 albedo, float shadow\n, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature\n) {\n\n\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation \n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);\n\n // Eval shading\n evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo\n,scattering, midNormalCurvature, lowNormalCurvature\n);\n \n lightEnergy *= isSpotEnabled();\n diffuse *= lightEnergy * isDiffuseEnabled();\n specular *= lightEnergy * isSpecularEnabled();\n\n if (isShowLightContour() > 0.0) {\n // Show edges\n float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance);\n float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume));\n float edgeDist = min(edgeDistR, edgeDistS);\n float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);\n if (edge < 1.0) {\n float edgeCoord = exp2(-8.0*edge*edge);\n diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light));\n }\n }\n}\n\n\n\nstruct FrustumGrid {\n float frustumNear;\n float rangeNear;\n float rangeFar;\n float frustumFar;\n ivec3 dims;\n float spare;\n mat4 eyeToGridProj;\n mat4 worldToEyeMat;\n mat4 eyeToWorldMat;\n};\n\nlayout(std140) uniform frustumGridBuffer {\n FrustumGrid frustumGrid;\n};\n\nfloat projection_getNear(mat4 projection) {\n float planeC = projection[2][3] + projection[2][2];\n float planeD = projection[3][2];\n return planeD / planeC;\n}\nfloat projection_getFar(mat4 projection) {\n //float planeA = projection[0][3] - projection[0][2]; All Zeros\n //float planeB = projection[1][3] - projection[1][2]; All Zeros\n float planeC = projection[2][3] - projection[2][2];\n float planeD = /*projection[3][3]*/ -projection[3][2];\n return planeD / planeC;\n}\n\n// glsl / C++ compatible source as interface for FrustrumGrid\n// glsl / C++ compatible source as interface for FrustrumGrid\n#if defined(Q_OS_LINUX)\n#define float_exp2 exp2f\n#else\n#define float_exp2 exp2\n#endif\n\nfloat frustumGrid_depthRampGridToVolume(float ngrid) {\n // return ngrid;\n // return sqrt(ngrid);\n return float_exp2(ngrid) - 1.0f;\n}\nfloat frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {\n // return nvolume;\n // return nvolume * nvolume;\n return log2(nvolume + 1.0f);\n}\n\nvec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {\n vec3 gridScale = vec3(1.0f) / vec3(dims);\n vec3 volumePos = pos * gridScale;\n volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);\n return volumePos;\n}\n\n\nfloat frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {\n return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);\n}\n\nvec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {\n vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);\n return gridPos;\n}\n\n\nvec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {\n vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);\n float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);\n vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);\n return clipPos;\n}\n\nvec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {\n return vec3(\n (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],\n (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],\n -clipPos.w\n //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]\n );\n}\n\nvec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {\n return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);\n}\n\nfloat frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {\n return (-eposZ - rangeNear) / (rangeFar - rangeNear);\n}\n\nvec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {\n vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],\n epos.y * projection[1][1] + epos.z * projection[2][1],\n epos.z * projection[2][2] + projection[2][3],\n -epos.z);\n vec4 ndcPos = clipPos / clipPos.w;\n\n vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));\n return volumePos;\n}\n\n\n\nint frustumGrid_numClusters() {\n return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);\n}\n\nint frustumGrid_clusterToIndex(ivec3 pos) {\n return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;\n}\nivec3 frustumGrid_indexToCluster(int index) {\n ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);\n int layer = index / summedDims.x;\n int offsetInLayer = index % summedDims.x;\n ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);\n return clusterPos;\n}\n\nvec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {\n\n vec3 cvpos = clusterPos;\n\n\n vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);\n\n vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n return eyePos;\n}\n\nvec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {\n vec3 cvpos = vec3(clusterPos) + offset;\n return frustumGrid_clusterPosToEye(cvpos);\n}\n\nint frustumGrid_eyeDepthToClusterLayer(float eyeZ) {\n if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {\n return -2;\n }\n\n if (eyeZ > -frustumGrid.rangeNear) {\n return -1;\n }\n\n float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));\n\n if (gridZ >= frustumGrid.dims.z) {\n gridZ = frustumGrid.dims.z;\n }\n\n\n return gridZ;\n}\n\nivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {\n\n // make sure the frontEyePos is always in the front to eval the grid pos correctly\n vec3 frontEyePos = eyePos;\n frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z);\n vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);\n\n\n vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);\n \n if (gridPos.z >= float(frustumGrid.dims.z)) {\n gridPos.z = float(frustumGrid.dims.z);\n }\n\n ivec3 igridPos = ivec3(floor(gridPos));\n\n if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {\n return ivec3(igridPos.x, igridPos.y, - 2);\n }\n\n if (eyePos.z > -frustumGrid.rangeNear) {\n return ivec3(igridPos.x, igridPos.y, -1);\n }\n\n return igridPos;\n}\n\n\nint frustumGrid_eyeToClusterDirH(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.x / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.x);\n\n return int(gridPos);\n}\n\nint frustumGrid_eyeToClusterDirV(vec3 eyeDir) {\n if (eyeDir.z >= 0.0f) {\n return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1);\n }\n\n float eyeDepth = -eyeDir.z;\n float nclipDir = eyeDir.y / eyeDepth;\n float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];\n float volumeDir = 0.5f * (ndcDir + 1.0f);\n float gridPos = volumeDir * float(frustumGrid.dims.y);\n\n return int(gridPos);\n}\n\nivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {\n return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));\n}\n\nvec4 frustumGrid_eyeToWorld(vec4 eyePos) {\n return frustumGrid.eyeToWorldMat * eyePos;\n}\n\nvec4 frustumGrid_worldToEye(vec4 worldPos) {\n return frustumGrid.worldToEyeMat * worldPos;\n}\n\n\n\n // End C++ compatible// end of hybrid include\n\n#define GRID_NUM_ELEMENTS 4096\n#define GRID_INDEX_TYPE ivec4\n#define GRID_FETCH_BUFFER(i) i / 4][i % 4\n\nlayout(std140) uniform clusterGridBuffer {\n GRID_INDEX_TYPE _clusterGridTable[GRID_NUM_ELEMENTS];\n};\n\nlayout(std140) uniform clusterContentBuffer {\n GRID_INDEX_TYPE _clusterGridContent[GRID_NUM_ELEMENTS];\n};\n\nivec3 clusterGrid_getCluster(int index) {\n int clusterDesc = _clusterGridTable[GRID_FETCH_BUFFER(index)];\n int numPointLights = 0xFF & (clusterDesc >> 16);\n int numSpotLights = 0xFF & (clusterDesc >> 24);\n int contentOffset = 0xFFFF & (clusterDesc);\n return ivec3(numPointLights, numSpotLights, contentOffset);\n}\n\nint clusterGrid_getClusterLightId(int index, int offset) {\n int elementIndex = offset + index;\n /*\n int element = _clusterGridContent[GRID_FETCH_BUFFER(elementIndex)];\n return element;\n */\n int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))];\n return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;\n}\n\n\nbool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {\n return numLights>0 \n && all(greaterThanEqual(clusterPos, ivec3(0))) \n && all(lessThan(clusterPos.xy, dims.xy))\n && clusterPos.z <= dims.z;\n}\n\nvec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,\n float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, \n\n\n vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {\n vec4 fragColor = vec4(0.0);\n vec3 fragSpecular = vec3(0.0);\n vec3 fragDiffuse = vec3(0.0);\n int lightClusterOffset = cluster.z;\n\n // Compute the rougness into gloss2 once:\n bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);\n\n int numLightTouching = 0;\n for (int i = 0; i < cluster.x; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n for (int i = cluster.x; i < numLights; i++) {\n // Need the light now\n int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);\n Light light = getLight(theLightIndex);\n\n // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space\n vec4 fragLightVecLen2;\n vec4 fragLightDirLen;\n float cosSpotAngle;\n\n if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {\n continue;\n }\n\n // Allright we re in the light sphere volume\n fragLightDirLen.w = length(fragLightVecLen2.xyz);\n fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;\n if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {\n continue;\n }\n\n // Check spot\n if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {\n continue;\n }\n\n numLightTouching++;\n\n vec3 diffuse = vec3(1.0);\n vec3 specular = vec3(0.1);\n\n // Allright we re valid in the volume\n float fragLightDistance = fragLightDirLen.w;\n vec3 fragLightDir = fragLightDirLen.xyz;\n\n updateSurfaceDataWithLight(surface, fragLightDir);\n\n // Eval attenuation\n float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);\n float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);\n vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);\n\n // Eval shading\n if (withScattering) {\n evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,\n fragScattering, midNormalCurvature, lowNormalCurvature );\n } else {\n evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);\n }\n\n diffuse *= lightEnergy;\n specular *= lightEnergy;\n\n fragDiffuse.rgb += diffuse;\n fragSpecular.rgb += specular;\n }\n\n fragDiffuse *= isDiffuseEnabled();\n fragSpecular *= isSpecularEnabled();\n\n fragColor.rgb += fragDiffuse;\n fragColor.rgb += fragSpecular / opacity;\n return fragColor;\n}// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define _MAT4 Mat4\n# define _VEC4 Vec4\n#\tdefine _MUTABLE mutable\n#else\n# define _MAT4 mat4\n# define _VEC4 vec4\n#\tdefine _MUTABLE \n#endif\n\nstruct _TransformCamera {\n _MUTABLE _MAT4 _view;\n _MUTABLE _MAT4 _viewInverse;\n _MUTABLE _MAT4 _projectionViewUntranslated;\n _MAT4 _projection;\n _MUTABLE _MAT4 _projectionInverse;\n _VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.\n _MUTABLE _VEC4 _stereoInfo;\n};\n\n // //\n\n#define TransformCamera _TransformCamera\n\nlayout(std140) uniform transformCameraBuffer {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n TransformCamera _camera[2];\n#else\n TransformCamera _camera;\n#endif\n#else\n TransformCamera _camera;\n#endif\n};\n\n#ifdef GPU_VERTEX_SHADER\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\nlayout(location=14) in int _inStereoSide;\n#endif\n\nlayout(location=14) flat out int _stereoSide;\n\n// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2\nint gpu_InstanceID() {\n return gl_InstanceID >> 1;\n}\n\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n#endif\n#else\n\nint gpu_InstanceID() {\n return gl_InstanceID;\n}\n\n#endif\n\n#endif\n\n#ifdef GPU_PIXEL_SHADER\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\nlayout(location=14) flat in int _stereoSide;\n#endif\n#endif\n\n\nTransformCamera getTransformCamera() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n #ifdef GPU_TRANSFORM_STEREO_CAMERA\n #ifdef GPU_VERTEX_SHADER\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED\n _stereoSide = _inStereoSide;\n #endif\n #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n _stereoSide = gl_InstanceID % 2;\n #endif\n #endif\n return _camera[_stereoSide];\n #else\n return _camera;\n #endif\n#else\n return _camera;\n#endif\n}\n\nvec3 getEyeWorldPos() {\n return getTransformCamera()._viewInverse[3].xyz;\n}\n\nbool cam_isStereo() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n return getTransformCamera()._stereoInfo.x > 0.0;\n#else\n return _camera._stereoInfo.x > 0.0;\n#endif\n}\n\nfloat cam_getStereoSide() {\n#ifdef GPU_TRANSFORM_IS_STEREO\n#ifdef GPU_TRANSFORM_STEREO_CAMERA\n return getTransformCamera()._stereoInfo.y;\n#else\n return _camera._stereoInfo.y;\n#endif\n#else\n return _camera._stereoInfo.y;\n#endif\n}\n\n\n\n#define TAA_TEXTURE_LOD_BIAS -1.0\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8\n\nstruct GPUTextureTable {\n uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];\n};\n\n#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }\n\n#define tableTex(name, slot) sampler2D(name._textures[slot].xy)\n#define tableTexMinLod(name, slot) float(name._textures[slot].z)\n\n#define tableTexValue(name, slot, uv) \\\n tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)\n \nvec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {\n float queryLod = textureQueryLod(sampler, uv).x;\n queryLod = max(minLod, queryLod);\n return textureLod(sampler, uv, queryLod);\n}\n \n#else\n\n#endif\n\n#ifdef GPU_TEXTURE_TABLE_BINDLESS\n\nTextureTable(0, matTex);\n#define albedoMap 0\nvec4 fetchAlbedoMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, albedoMap, uv);\n}\n#define roughnessMap 4\nfloat fetchRoughnessMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, roughnessMap, uv).r;\n}\n#define normalMap 1\nvec3 fetchNormalMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, normalMap, uv).xyz;\n}\n#define emissiveMap 3\nvec3 fetchEmissiveMap(vec2 uv) {\n // Should take into account TAA_TEXTURE_LOD_BIAS?\n return tableTexValue(matTex, emissiveMap, uv).rgb;\n}\n#define occlusionMap 5\nfloat fetchOcclusionMap(vec2 uv) {\n return tableTexValue(matTex, occlusionMap, uv).r;\n}\n#else\n\nuniform sampler2D albedoMap;\nvec4 fetchAlbedoMap(vec2 uv) {\n return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);\n}\nuniform sampler2D roughnessMap;\nfloat fetchRoughnessMap(vec2 uv) {\n return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);\n}\nuniform sampler2D normalMap;\nvec3 fetchNormalMap(vec2 uv) {\n // unpack normal, swizzle to get into hifi tangent space with Y axis pointing out\n vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));\n vec2 t2 = t*t;\n return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);\n}\nuniform sampler2D emissiveMap;\nvec3 fetchEmissiveMap(vec2 uv) {\n return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;\n}\nuniform sampler2D occlusionMap;\nfloat fetchOcclusionMap(vec2 uv) {\n return texture(occlusionMap, uv).r;\n}\n#endif\n\n\n\n// Generated on Wed May 23 14:24:09 2018\n//\n// Created by Olivier Prat on 04/12/17.\n// Copyright 2017 High Fidelity, Inc.\n//\n// Distributed under the Apache License, Version 2.0.\n// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html\n//\n#define CATEGORY_COUNT 5\n\n// glsl / C++ compatible source as interface for FadeEffect\n#ifdef __cplusplus\n# define VEC4 glm::vec4\n\n\n# define VEC2 glm::vec2\n# define FLOAT32 glm::float32\n# define INT32 glm::int32\n#else\n# define VEC4 vec4\n# define VEC2 vec2\n# define FLOAT32 float\n# define INT32 int\n#endif\n\nstruct FadeParameters\n{\n\tVEC4 _noiseInvSizeAndLevel;\n\tVEC4 _innerEdgeColor;\n\tVEC4 _outerEdgeColor;\n\tVEC2 _edgeWidthInvWidth;\n\tFLOAT32 _baseLevel;\n\tINT32 _isInverted;\n};\n\n // //\nlayout(std140) uniform fadeParametersBuffer {\n FadeParameters fadeParameters[CATEGORY_COUNT];\n};\nuniform sampler2D fadeMaskMap;\n\nstruct FadeObjectParams {\n int category;\n float threshold;\n vec3 noiseOffset;\n vec3 baseOffset;\n vec3 baseInvSize;\n};\n\nvec2 hash2D(vec3 position) {\n return position.xy* vec2(0.1677, 0.221765) + position.z*0.561;\n}\n\nfloat noise3D(vec3 position) {\n float n = textureLod(fadeMaskMap, hash2D(position), 0.0).r;\n return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture\n}\n\nfloat evalFadeNoiseGradient(FadeObjectParams params, vec3 position) {\n // Do tri-linear interpolation\n vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset;\n vec3 noisePositionFloored = floor(noisePosition);\n vec3 noisePositionFraction = fract(noisePosition);\n\n noisePositionFraction = noisePositionFraction*noisePositionFraction*(3.0 - 2.0*noisePositionFraction);\n\n float noiseLowXLowYLowZ = noise3D(noisePositionFloored);\n float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0));\n float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0));\n float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0));\n float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1));\n float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1));\n float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1));\n float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1));\n vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ);\n vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ);\n vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);\n vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);\n\n float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);\n noise -= 0.5; // Center on value 0\n return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w;\n}\n\nfloat evalFadeBaseGradient(FadeObjectParams params, vec3 position) {\n float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz);\n gradient = gradient-0.5; // Center on value 0.5\n gradient *= fadeParameters[params.category]._baseLevel;\n return gradient;\n}\n\nfloat evalFadeGradient(FadeObjectParams params, vec3 position) {\n float baseGradient = evalFadeBaseGradient(params, position);\n float noiseGradient = evalFadeNoiseGradient(params, position);\n float gradient = noiseGradient+baseGradient+0.5;\n\n return gradient;\n}\n\nfloat evalFadeAlpha(FadeObjectParams params, vec3 position) {\n return evalFadeGradient(params, position)-params.threshold;\n}\n\nvoid applyFadeClip(FadeObjectParams params, vec3 position) {\n if (evalFadeAlpha(params, position) < 0.0) {\n discard;\n }\n}\n\nvoid applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) {\n float alpha = evalFadeAlpha(params, position);\n if (fadeParameters[params.category]._isInverted!=0) {\n alpha = -alpha;\n }\n\n if (alpha < 0.0) {\n discard;\n }\n \n float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y;\n float edgeAlpha = 1.0-clamp(edgeMask, 0.0, 1.0);\n\n edgeMask = step(edgeMask, 1.0);\n edgeAlpha *= edgeAlpha; // Square to have a nice ease out\n vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha);\n emissive = color.rgb * edgeMask * color.a;\n}\n\n\nuniform int fadeCategory;\nuniform vec3 fadeNoiseOffset;\nuniform vec3 fadeBaseOffset;\nuniform vec3 fadeBaseInvSize;\nuniform float fadeThreshold;\n\n\n\n\nin vec2 _texCoord0;\nin vec2 _texCoord1;\nin vec4 _positionES;\nin vec3 _normalWS;\nin vec3 _tangentWS;\nin vec3 _color;\nin float _alpha;\nin vec4 _positionWS;\n\nout vec4 _fragColor;\n\nvoid main(void) {\n vec3 fadeEmissive;\n FadeObjectParams fadeParams;\n\n fadeParams.category = fadeCategory;\n fadeParams.threshold = fadeThreshold;\n fadeParams.noiseOffset = fadeNoiseOffset;\n fadeParams.baseOffset = fadeBaseOffset;\n fadeParams.baseInvSize = fadeBaseInvSize;\n\n applyFade(fadeParams, _positionWS.xyz, fadeEmissive);\n\n Material mat = getMaterial();\n int matKey = getMaterialKey(mat);\n vec4 albedoTex = (((matKey & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(_texCoord0) : vec4(1.0));\nfloat roughnessTex = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(_texCoord0) : 1.0);\nvec3 normalTex = (((matKey & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(_texCoord0) : vec3(0.0, 1.0, 0.0));\nvec3 emissiveTex = (((matKey & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(_texCoord0) : vec3(0.0));\n\n float occlusionTex = (((matKey & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(_texCoord1) : 1.0);\n\n\n float opacity = getMaterialOpacity(mat) * _alpha;\n {\n const float OPACITY_MASK_THRESHOLD = 0.5;\n opacity = (((matKey & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ?\n (((matKey & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, albedoTex.a) : albedoTex.a) :\n 1.0) * opacity;\n}\n;\n\n vec3 albedo = getMaterialAlbedo(mat);\n {\n albedo.xyz = (((matKey & ALBEDO_VAL_BIT) != 0) ? albedo : vec3(1.0));\n\n if (((matKey & ALBEDO_MAP_BIT) != 0)) {\n albedo.xyz *= albedoTex.xyz;\n }\n}\n;\n albedo *= _color;\n\n float roughness = getMaterialRoughness(mat);\n {\n roughness = (((matKey & ROUGHNESS_MAP_BIT) != 0) ? roughnessTex : roughness);\n}\n;\n\n float metallic = getMaterialMetallic(mat);\n vec3 fresnel = getFresnelF0(metallic, albedo);\n\n vec3 emissive = getMaterialEmissive(mat);\n {\n emissive = (((matKey & EMISSIVE_MAP_BIT) != 0) ? emissiveTex : emissive);\n}\n;\n\n vec3 fragPositionES = _positionES.xyz;\n vec3 fragPositionWS = _positionWS.xyz;\n // Lighting is done in world space\n vec3 fragNormalWS;\n {\n vec3 normalizedNormal = normalize(_normalWS.xyz);\n vec3 normalizedTangent = normalize(_tangentWS.xyz);\n vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);\n // attenuate the normal map divergence from the mesh normal based on distance\n // The attenuation range [30,100] meters from the eye is arbitrary for now\n vec3 localNormal = mix(normalTex, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-_positionES).z));\n fragNormalWS = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);\n}\n\n\n TransformCamera cam = getTransformCamera();\n vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;\n vec3 fragToEyeDirWS = normalize(fragToEyeWS);\n SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);\n\n vec4 localLighting = vec4(0.0);\n\n // From frag world pos find the cluster\n vec4 clusterEyePos = frustumGrid_worldToEye(_positionWS);\n ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);\n\n ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));\n int numLights = cluster.x + cluster.y;\n ivec3 dims = frustumGrid.dims.xyz;\n\n;\n if (hasLocalLights(numLights, clusterPos, dims)) {\n localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,\n metallic, fresnel, albedo, 0.0,\n vec4(0), vec4(0), opacity);\n }\n\n _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(\n cam._viewInverse,\n 1.0,\n occlusionTex,\n fragPositionES,\n\t\tfragPositionWS,\n albedo,\n fresnel,\n metallic,\n emissive + fadeEmissive,\n surfaceWS, opacity, localLighting.rgb),\n opacity);\n}\n\n\n" } }